phase 0 complete
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package httpserver
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// spaHandler serves the embedded Vue SPA out of distFS (already rooted at
|
||||
// web/dist, i.e. index.html is at its top level). Any request path that
|
||||
// doesn't match a real file falls back to index.html so client-side routes
|
||||
// (deep links) resolve correctly.
|
||||
func spaHandler(distFS fs.FS) http.HandlerFunc {
|
||||
fileServer := http.FileServer(http.FS(distFS))
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
upath := r.URL.Path
|
||||
if upath == "" || upath == "/" {
|
||||
upath = "index.html"
|
||||
} else {
|
||||
upath = upath[1:] // strip leading slash for fs.Stat
|
||||
}
|
||||
|
||||
if _, err := fs.Stat(distFS, upath); err != nil {
|
||||
r = cloneWithPath(r, "/")
|
||||
}
|
||||
|
||||
fileServer.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// cloneWithPath returns a shallow copy of r with URL.Path replaced, so the
|
||||
// original request (and its URL) is left untouched.
|
||||
func cloneWithPath(r *http.Request, path string) *http.Request {
|
||||
r2 := r.Clone(r.Context())
|
||||
r2.URL.Path = path
|
||||
return r2
|
||||
}
|
||||
Reference in New Issue
Block a user