package server import ( "embed" "fmt" "io/fs" "net/http" "path" "strings" ) //go:embed ui-dist/* var uiDist embed.FS type uiRenderer struct { fsys fs.FS } func newUIRenderer() *uiRenderer { sub, err := fs.Sub(uiDist, "ui-dist") if err != nil { return &uiRenderer{} } return &uiRenderer{fsys: sub} } func (u *uiRenderer) ServeIndex(w http.ResponseWriter, _ *http.Request) error { if u.fsys == nil { return fmt.Errorf("UI assets are not available") } body, err := fs.ReadFile(u.fsys, "index.html") if err != nil { return fmt.Errorf("read index: %w", err) } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-store") _, _ = w.Write(body) return nil } func (u *uiRenderer) ServeAsset(w http.ResponseWriter, r *http.Request) bool { if u.fsys == nil { return false } if r.Method != http.MethodGet && r.Method != http.MethodHead { return false } requestPath := strings.TrimPrefix(r.URL.Path, "/") if requestPath == "" || requestPath == "." { return false } if strings.HasPrefix(requestPath, "v1/") { return false } cleaned := path.Clean(requestPath) if cleaned == "." || strings.HasPrefix(cleaned, "../") { return false } if strings.HasSuffix(cleaned, "/") { return false } if _, err := fs.Stat(u.fsys, cleaned); err != nil { return false } http.FileServer(http.FS(u.fsys)).ServeHTTP(w, r) return true }