package main import ( "net/http" "os" "path" "path/filepath" "strings" ) func (a *app) handler() http.Handler { api := a.routes() webDir := strings.TrimSpace(a.cfg.WebDir) if webDir == "" { return api } indexPath := filepath.Join(webDir, "index.html") return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/health" { a.healthHandler(w, r) return } if isBackendPath(r.URL.Path) { api.ServeHTTP(w, r) return } cleanPath := path.Clean("/" + r.URL.Path) relativePath := strings.TrimPrefix(cleanPath, "/") if relativePath != "" { candidate := filepath.Join(webDir, filepath.FromSlash(relativePath)) if info, err := os.Stat(candidate); err == nil && !info.IsDir() { http.ServeFile(w, r, candidate) return } // Missing static assets should be real 404s rather than the SPA shell. if filepath.Ext(relativePath) != "" { http.NotFound(w, r) return } } if _, err := os.Stat(indexPath); err != nil { api.ServeHTTP(w, r) return } http.ServeFile(w, r, indexPath) }) } func isBackendPath(requestPath string) bool { switch { case requestPath == "/api", strings.HasPrefix(requestPath, "/api/"): return true case requestPath == "/auth", strings.HasPrefix(requestPath, "/auth/"): return true case requestPath == "/.well-known", strings.HasPrefix(requestPath, "/.well-known/"): return true case requestPath == "/sitemap.xml", requestPath == "/robots.txt": return true default: return false } }