Files
Luminary/internal/handler/static/handler.go
T
renjue 76ba500417
CI / docker (push) Successful in 2m4s
Initial commit: Luminary AI Gateway
OpenAI-compatible AI gateway with Vue admin UI, multi-provider egress,
ingress key governance, monitoring, and security controls.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 21:46:16 +08:00

64 lines
1.4 KiB
Go

package static
import (
"embed"
"io/fs"
"mime"
"net/http"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
)
type Handler struct {
content embed.FS
}
func New(content embed.FS) *Handler {
return &Handler{content: content}
}
func (h *Handler) Register(r *gin.Engine) {
sub, err := fs.Sub(h.content, "dist")
if err != nil {
sub = h.content
}
r.NoRoute(func(c *gin.Context) {
if strings.HasPrefix(c.Request.URL.Path, "/api/") || strings.HasPrefix(c.Request.URL.Path, "/v1/") {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
h.serve(c, sub)
})
r.GET("/", func(c *gin.Context) { h.serve(c, sub) })
r.GET("/assets/*filepath", func(c *gin.Context) { h.serve(c, sub) })
}
func (h *Handler) serve(c *gin.Context, sub fs.FS) {
path := strings.TrimPrefix(c.Request.URL.Path, "/")
if path == "" {
path = "index.html"
}
data, err := fs.ReadFile(sub, path)
if err != nil {
data, err = fs.ReadFile(sub, "index.html")
if err != nil {
c.String(http.StatusNotFound, "UI not built. Run: make build-web")
return
}
path = "index.html"
}
ext := filepath.Ext(path)
ct := mime.TypeByExtension(ext)
if ct == "" {
ct = "text/html"
}
if strings.HasPrefix(path, "assets/") {
c.Header("Cache-Control", "public, max-age=31536000, immutable")
} else {
c.Header("Cache-Control", "no-cache")
}
c.Data(http.StatusOK, ct, data)
}