63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package admin
|
|
|
|
import (
|
|
"embed"
|
|
"io"
|
|
"io/fs"
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
//go:embed all:dist
|
|
var frontendAssets embed.FS
|
|
|
|
// serveSPA serves the frontend SPA with fallback to index.html for client-side routing.
|
|
func (s *AdminServer) serveSPA() http.Handler {
|
|
// Get the dist subdirectory from embedded files
|
|
distFS, err := fs.Sub(frontendAssets, "dist")
|
|
if err != nil {
|
|
s.logger.Error("failed to access frontend assets", "error", err)
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
http.Error(w, "Admin UI not available", http.StatusNotFound)
|
|
})
|
|
}
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Path comes in without /admin prefix due to StripPrefix
|
|
urlPath := r.URL.Path
|
|
if urlPath == "" || urlPath == "/" {
|
|
urlPath = "index.html"
|
|
} else {
|
|
// Remove leading slash
|
|
urlPath = strings.TrimPrefix(urlPath, "/")
|
|
}
|
|
|
|
// Clean the path
|
|
cleanPath := path.Clean(urlPath)
|
|
|
|
// Try to open the file
|
|
file, err := distFS.Open(cleanPath)
|
|
if err != nil {
|
|
// File not found, serve index.html for SPA routing
|
|
cleanPath = "index.html"
|
|
file, err = distFS.Open(cleanPath)
|
|
if err != nil {
|
|
http.Error(w, "Not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}
|
|
defer file.Close()
|
|
|
|
// Get file info for content type detection
|
|
info, err := file.Stat()
|
|
if err != nil {
|
|
http.Error(w, "Internal error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Serve the file
|
|
http.ServeContent(w, r, cleanPath, info.ModTime(), file.(io.ReadSeeker))
|
|
})
|
|
}
|