MCPcopy Index your code
hub / github.com/PatchMon/PatchMon / SPAHandler

Function SPAHandler

server-source-code/internal/server/static.go:11–42  ·  view source on GitHub ↗

SPAHandler serves static files from the given FS, falling back to index.html for SPA routing. index.html is served with Cache-Control: no-cache so browsers always fetch the latest version. Hashed asset files (JS/CSS) rely on Vite content-hash filenames and can be cached long-term.

(fsys fs.FS)

Source from the content-addressed store, hash-verified

9// index.html is served with Cache-Control: no-cache so browsers always fetch the latest version.
10// Hashed asset files (JS/CSS) rely on Vite content-hash filenames and can be cached long-term.
11func SPAHandler(fsys fs.FS) http.Handler {
12 fileServer := http.FileServer(http.FS(fsys))
13 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14 path := r.URL.Path
15 if len(path) > 0 && path[0] == '/' {
16 path = path[1:]
17 }
18 if path == "" {
19 path = "index.html"
20 }
21
22 f, err := fsys.Open(path)
23 if err == nil {
24 _ = f.Close()
25 if path == "index.html" || path == "" {
26 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
27 w.Header().Set("Pragma", "no-cache")
28 w.Header().Set("Expires", "0")
29 }
30 fileServer.ServeHTTP(w, r)
31 return
32 }
33
34 // fall back to index.html for client-side routing
35 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
36 w.Header().Set("Pragma", "no-cache")
37 w.Header().Set("Expires", "0")
38 r2 := r.Clone(r.Context())
39 r2.URL.Path = "/"
40 fileServer.ServeHTTP(w, r2)
41 })
42}

Callers 1

NewRouterFunction · 0.85

Calls 2

CloseMethod · 0.45
SetMethod · 0.45

Tested by

no test coverage detected