package main import ( "context" _ "embed" "fmt" "net/http" "os" "strings" ) type Context struct { User string } func HTTP(port int, db DB) error { foo := func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/": httpRoot(w, r) default: http.NotFound(w, r) } } foo = withAuth(foo) return http.ListenAndServe(fmt.Sprintf(":%d", port), http.HandlerFunc(foo)) } func extract(ctx context.Context) Context { v := ctx.Value("__context") v2, _ := v.(Context) return v2 } func inject(ctx context.Context, v Context) context.Context { return context.WithValue(ctx, "__context", v) } func withAuth(foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { u, _, ok := r.BasicAuth() if !ok || u == "" { w.Header().Set("WWW-Authenticate", "Basic") w.WriteHeader(401) return } c := extract(r.Context()) c.User = u r = r.WithContext(inject(r.Context(), c)) foo(w, r) } } //go:embed public/root.html var httpRootHTML string func httpRoot(w http.ResponseWriter, r *http.Request) { body := httpRootHTML if os.Getenv("DEBUG") != "" { b, _ := os.ReadFile("public/root.html") body = string(b) } ctx := extract(r.Context()) body = strings.ReplaceAll(body, "{{USER}}", ctx.User) w.Write([]byte(body)) }