Serve Static Files with SPA Fallback
Serve a built frontend from disk, fall back to index.html for extensionless routes, and return 404 for missing assets.
Code
package main
import (
"fmt"
"net/http"
"os"
"path"
)
func SPAHandler(root http.FileSystem) http.Handler {
files := http.FileServer(root)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cleaned := path.Clean("/" + r.URL.Path)
if cleaned != "/" {
file, err := root.Open(cleaned)
if err == nil {
info, statErr := file.Stat()
_ = file.Close()
if statErr != nil || info.IsDir() {
r.URL.Path = "/"
}
} else if path.Ext(cleaned) == "" {
r.URL.Path = "/"
}
}
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Cache-Control", "public, max-age=300")
files.ServeHTTP(w, r)
})
}
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
fmt.Println("serving dist on port", port)
_ = http.ListenAndServe(":"+port, SPAHandler(http.Dir("dist")))
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.