github.com/pojntfx/hydrapp/hydrapp@v0.0.0-20240516002902-d08759d6ca9f/pkg/generators/frontend_vanillajs_forms.go.tpl (about)

     1  package frontend
     2  
     3  import (
     4  	"context"
     5  	_ "embed"
     6  	"html/template"
     7  	"net"
     8  	"net/http"
     9  	"net/url"
    10  	"runtime"
    11  	"strings"
    12  	"sync"
    13  	"time"
    14  
    15  	"github.com/google/uuid"
    16  	"github.com/pojntfx/hydrapp/hydrapp/pkg/utils"
    17  )
    18  
    19  var (
    20  	//go:embed index.html
    21  	indexHTML string
    22  )
    23  
    24  type todo struct {
    25  	Title string
    26  	Body  string
    27  }
    28  
    29  type data struct {
    30  	Todos map[string]todo
    31  
    32  	GoVersion,
    33  	GoOS,
    34  	GoArch,
    35  	RenderTime string
    36  }
    37  
    38  func StartServer(ctx context.Context, addr string, localhostize bool) (string, func() error, error) {
    39  	if strings.TrimSpace(addr) == "" {
    40  		addr = ":0"
    41  	}
    42  
    43  	listener, err := net.Listen("tcp", addr)
    44  	if err != nil {
    45  		return "", nil, err
    46  	}
    47  
    48  	index, err := template.New("index.html").Parse(indexHTML)
    49  	if err != nil {
    50  		return "", nil, err
    51  	}
    52  
    53  	todos := map[string]todo{}
    54  	var todosLock sync.Mutex
    55  
    56  	mux := http.NewServeMux()
    57  
    58  	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    59  		if err := index.Execute(
    60  			w,
    61  			data{
    62  				Todos: todos,
    63  
    64  				GoVersion:  runtime.Version(),
    65  				GoOS:       runtime.GOOS,
    66  				GoArch:     runtime.GOARCH,
    67  				RenderTime: time.Now().Format(time.RFC3339),
    68  			},
    69  		); err != nil {
    70  			panic(err)
    71  		}
    72  	})
    73  
    74  	mux.HandleFunc("/create", func(w http.ResponseWriter, r *http.Request) {
    75  		if err := r.ParseForm(); err != nil {
    76  			panic(err)
    77  		}
    78  
    79  		todosLock.Lock()
    80  		defer todosLock.Unlock()
    81  
    82  		todos[uuid.NewString()] = todo{r.FormValue("title"), r.FormValue("body")}
    83  
    84  		http.Redirect(w, r, r.Header.Get("Referer"), http.StatusFound)
    85  	})
    86  
    87  	mux.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) {
    88  		todosLock.Lock()
    89  		defer todosLock.Unlock()
    90  
    91  		delete(todos, r.URL.Query().Get("id"))
    92  
    93  		http.Redirect(w, r, r.Header.Get("Referer"), http.StatusFound)
    94  	})
    95  
    96  	go func() {
    97  		if err := http.Serve(listener, mux); err != nil {
    98  			if strings.HasSuffix(err.Error(), "use of closed network connection") {
    99  				return
   100  			}
   101  
   102  			panic(err)
   103  		}
   104  	}()
   105  
   106  	url, err := url.Parse("http://" + listener.Addr().String())
   107  	if err != nil {
   108  		return "", nil, err
   109  	}
   110  
   111  	if localhostize {
   112  		return utils.Localhostize(url.String()), listener.Close, nil
   113  	}
   114  
   115  	return url.String(), listener.Close, nil
   116  }