package static import ( "io/fs" "net/http" "path" ) type SPAHandler struct { assets fs.FS files http.Handler } func NewSPAHandler() (http.Handler, error) { sub, err := fs.Sub(DistFS, "dist") if err != nil { return nil, err } return &SPAHandler{ assets: sub, files: http.FileServer(http.FS(sub)), }, nil } func (h *SPAHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { requested := path.Clean(r.URL.Path) if requested == "." || requested == "/" { h.serveIndex(w, r) return } candidate := requested[1:] if candidate == "" { h.serveIndex(w, r) return } if file, err := h.assets.Open(candidate); err == nil { _ = file.Close() h.files.ServeHTTP(w, r) return } h.serveIndex(w, r) } func (h *SPAHandler) serveIndex(w http.ResponseWriter, r *http.Request) { index, err := fs.ReadFile(h.assets, "index.html") if err != nil { http.Error(w, "index.html not found", http.StatusNotFound) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = w.Write(index) }