fix: serve SvelteKit _app assets correctly

- Use all: prefix in go:embed to include _app/ directory (Go skips
  _-prefixed dirs by default)
- Move jsonContentType middleware to /api route group only
- Use http.ServeContent for proper MIME type detection
- Remove unused fileServer variable
This commit is contained in:
2026-03-28 13:34:02 +03:00
parent 652229c67f
commit 4d4e07eb2e
3 changed files with 21 additions and 14 deletions
+3 -1
View File
@@ -88,9 +88,11 @@ func (s *Server) Router() chi.Router {
r.Use(recovery)
r.Use(logging)
r.Use(cors)
r.Use(jsonContentType)
r.Route("/api", func(r chi.Router) {
// JSON content type only for API routes (not static files).
r.Use(jsonContentType)
// Public auth endpoints (no auth required).
r.Post("/auth/login", s.login)
r.Get("/auth/oidc/login", s.oidcLogin)
+17 -12
View File
@@ -1,6 +1,7 @@
package api
import (
"io"
"io/fs"
"net/http"
"strings"
@@ -9,8 +10,6 @@ import (
// StaticHandler serves embedded SPA files with fallback to index.html
// for all non-API routes (SPA client-side routing support).
func StaticHandler(webFS fs.FS) http.Handler {
fileServer := http.FileServer(http.FS(webFS))
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Skip API routes — they are handled by the API router.
if strings.HasPrefix(r.URL.Path, "/api") {
@@ -18,25 +17,31 @@ func StaticHandler(webFS fs.FS) http.Handler {
return
}
// Try to serve the exact file.
// Try to serve the exact file from the embedded FS.
path := strings.TrimPrefix(r.URL.Path, "/")
if path == "" {
path = "index.html"
}
// Check if file exists in the embedded FS.
f, err := webFS.Open(path)
if err == nil {
if f, err := webFS.Open(path); err == nil {
stat, statErr := f.Stat()
f.Close()
// Clear the JSON content-type set by middleware — let file server decide.
w.Header().Del("Content-Type")
fileServer.ServeHTTP(w, r)
return
if statErr == nil && !stat.IsDir() {
// Serve the actual file. Use http.ServeContent for correct MIME detection.
file, _ := webFS.Open(path)
defer file.Close()
http.ServeContent(w, r, stat.Name(), stat.ModTime(), file.(io.ReadSeeker))
return
}
}
// File not found: serve index.html for SPA client-side routing.
r.URL.Path = "/"
w.Header().Del("Content-Type")
fileServer.ServeHTTP(w, r)
indexFile, _ := webFS.Open("index.html")
if indexFile != nil {
defer indexFile.Close()
stat, _ := indexFile.Stat()
http.ServeContent(w, r, "index.html", stat.ModTime(), indexFile.(io.ReadSeeker))
}
})
}