Files
Christoph K. d0b0b4f8bd
Some checks failed
Deploy to NAS / deploy (push) Failing after 4s
Convert backend from submodule to regular directory
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>
2026-04-07 16:59:50 +02:00

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)
})
}