Some checks failed
Deploy to NAS / deploy (push) Failing after 4s
Remove submodule tracking; backend is now a plain directory in the repo. Also update deploy workflow: remove --recurse-submodules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
package api
|
|
|
|
import (
|
|
"embed"
|
|
"io/fs"
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// spaFS holds the built Vite SPA.
|
|
// The directory backend/internal/api/webapp/ is populated by the Docker
|
|
// multi-stage build (node → copy dist → go build).
|
|
// A placeholder file keeps the embed valid when building without Docker.
|
|
|
|
//go:embed webapp
|
|
var spaFS embed.FS
|
|
|
|
// SPAHandler serves the Vite SPA under the given prefix (e.g. "/app").
|
|
// Static assets (paths with file extensions) are served directly.
|
|
// All other paths fall back to index.html for client-side routing.
|
|
func SPAHandler(prefix string) http.Handler {
|
|
sub, err := fs.Sub(spaFS, "webapp")
|
|
if err != nil {
|
|
return http.NotFoundHandler()
|
|
}
|
|
fileServer := http.FileServer(http.FS(sub))
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Strip the mount prefix to get the file path
|
|
path := strings.TrimPrefix(r.URL.Path, prefix)
|
|
if path == "" || path == "/" {
|
|
// Serve index.html
|
|
r2 := r.Clone(r.Context())
|
|
r2.URL.Path = "/index.html"
|
|
fileServer.ServeHTTP(w, r2)
|
|
return
|
|
}
|
|
|
|
// Has a file extension → serve asset directly (JS, CSS, fonts, …)
|
|
if filepath.Ext(path) != "" {
|
|
r2 := r.Clone(r.Context())
|
|
r2.URL.Path = path
|
|
fileServer.ServeHTTP(w, r2)
|
|
return
|
|
}
|
|
|
|
// SPA route → serve index.html
|
|
r2 := r.Clone(r.Context())
|
|
r2.URL.Path = "/index.html"
|
|
fileServer.ServeHTTP(w, r2)
|
|
})
|
|
}
|