// Package adminui serves the compiled management console from the API binary. package adminui import ( "embed" "io/fs" "net/http" "path" "strings" ) //go:embed all:dist var assets embed.FS func Handler() http.Handler { root, _ := fs.Sub(assets, "dist") files := http.FileServer(http.FS(root)) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet && r.Method != http.MethodHead { w.Header().Set("Allow", "GET, HEAD") http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } name := strings.TrimPrefix(path.Clean("/"+r.URL.Path), "/") if strings.HasPrefix(name, ".") || strings.Contains(name, "/.") { http.NotFound(w, r) return } if _, err := fs.Stat(root, "index.html"); err != nil { http.Error(w, "Management console not built. Run npm --prefix web/admin run build, then rebuild the Go executable.", http.StatusServiceUnavailable) return } if name != "" && name != "." { if info, err := fs.Stat(root, name); err == nil && !info.IsDir() { files.ServeHTTP(w, r) return } } if path.Ext(name) != "" || strings.HasPrefix(name, "assets/") { http.NotFound(w, r) return } index, err := fs.ReadFile(root, "index.html") if err != nil { http.Error(w, "Management console unavailable", http.StatusServiceUnavailable) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-cache") w.WriteHeader(http.StatusOK) if r.Method != http.MethodHead { _, _ = w.Write(index) } }) }