57 lines
1.5 KiB
Go
57 lines
1.5 KiB
Go
package api
|
|
|
|
import (
|
|
"io/fs"
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"oci-portal/internal/webui"
|
|
)
|
|
|
|
// registerWebUI 挂载嵌入的前端产物。dev 模式走 vite devServer,不经此路径。
|
|
func registerWebUI(r *gin.Engine) error {
|
|
sub, err := webui.Dist()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
mountSPA(r, sub)
|
|
return nil
|
|
}
|
|
|
|
// mountSPA 注册 NoRoute 兜底:命中真实文件直出,API 前缀保持 JSON 404,
|
|
// 其余路径回 index.html 交给 SPA 路由。
|
|
func mountSPA(r *gin.Engine, sub fs.FS) {
|
|
fileServer := http.FileServer(http.FS(sub))
|
|
r.NoRoute(func(c *gin.Context) {
|
|
p := c.Request.URL.Path
|
|
if strings.HasPrefix(p, "/api/") || strings.HasPrefix(p, "/ai/") {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
|
|
return
|
|
}
|
|
if name := strings.TrimPrefix(path.Clean(p), "/"); name != "" {
|
|
if _, err := fs.Stat(sub, name); err == nil {
|
|
setStaticCacheHeader(c, p)
|
|
fileServer.ServeHTTP(c.Writer, c.Request)
|
|
return
|
|
}
|
|
}
|
|
// SPA 路由统一回 index.html,禁缓存保证发版后入口即时更新
|
|
c.Header("Cache-Control", "no-cache")
|
|
c.Request.URL.Path = "/"
|
|
fileServer.ServeHTTP(c.Writer, c.Request)
|
|
})
|
|
}
|
|
|
|
// setStaticCacheHeader 按路径设缓存策略:vite 产物带内容 hash,/assets/* 可永久缓存;
|
|
// 其余真实文件(favicon 等)不带 hash,禁强缓存。
|
|
func setStaticCacheHeader(c *gin.Context, p string) {
|
|
if strings.HasPrefix(p, "/assets/") {
|
|
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
|
return
|
|
}
|
|
c.Header("Cache-Control", "no-cache")
|
|
}
|