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 }