package status import ( "embed" "html/template" "io/fs" "net/http" "sync" "sync/atomic" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) //go:embed templates/*.gotpl var templates embed.FS //go:embed public/* var public embed.FS type Handler struct { status *atomic.Value public http.Handler templates *template.Template init sync.Once initErr error } // ServeHTTP implements http.Handler. func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.init.Do(func() { root, err := fs.Sub(public, "public") if err != nil { h.initErr = errors.WithStack(err) return } h.public = http.FileServer(http.FS(root)) tmpl, err := template.ParseFS(templates, "templates/*.gotpl") if err != nil { h.initErr = errors.WithStack(err) return } h.templates = tmpl }) if h.initErr != nil { logger.Error(r.Context(), "could not initialize handler", logger.E(h.initErr)) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } switch r.URL.Path { case "/": h.serveIndex(w, r) default: h.public.ServeHTTP(w, r) } } func (h *Handler) serveIndex(w http.ResponseWriter, r *http.Request) { data := h.status.Load() if err := h.templates.ExecuteTemplate(w, "index.html.gotpl", data); err != nil { logger.Error(r.Context(), "could not render template", logger.E(errors.WithStack(err))) return } } var _ http.Handler = &Handler{}