Files
perler-beads-server/internal/server/static.go
T

60 lines
1.6 KiB
Go

package server
import (
"fmt"
"github.com/gin-gonic/gin"
"os"
"path/filepath"
"strings"
)
func validateWebUIDir(dir string) error {
info, e := os.Stat(filepath.Join(dir, "index.html"))
if e != nil || info.IsDir() {
return fmt.Errorf("WEBUI_DIR must contain index.html")
}
return nil
}
func within(root, path string) bool {
rel, e := filepath.Rel(root, path)
return e == nil && rel != ".." && !strings.HasPrefix(rel, ".."+string(os.PathSeparator))
}
func (s *Server) staticFallback(c *gin.Context) {
if c.Request.URL.Path == "/api" || strings.HasPrefix(c.Request.URL.Path, "/api/") || s.WebUIDir == "" || c.Request.Method != "GET" && c.Request.Method != "HEAD" {
reply(c, 404, "接口不存在", nil)
return
}
root, e := filepath.EvalSymlinks(s.WebUIDir)
if e != nil {
reply(c, 404, "页面不存在", nil)
return
}
root, e = filepath.Abs(root)
if e != nil {
reply(c, 404, "页面不存在", nil)
return
}
candidate := filepath.Join(root, filepath.FromSlash(strings.TrimPrefix(c.Request.URL.Path, "/")))
if !within(root, candidate) {
reply(c, 404, "页面不存在", nil)
return
}
if resolved, e := filepath.EvalSymlinks(candidate); e == nil {
if !within(root, resolved) {
reply(c, 404, "页面不存在", nil)
return
}
if info, e := os.Stat(resolved); e == nil && !info.IsDir() {
c.File(resolved)
return
}
}
index, e := filepath.EvalSymlinks(filepath.Join(root, "index.html"))
if e != nil || !within(root, index) {
reply(c, 404, "页面不存在", nil)
return
}
c.Header("Cache-Control", "no-cache")
c.File(index)
}