fix 线程死锁问题,前端加入打包
This commit is contained in:
+64
-1
@@ -12,6 +12,7 @@ import (
|
||||
"math/rand" // 随机数(刷盘时打乱顺序、概率性去重/裁剪)
|
||||
"net/http" // HTTP 服务端
|
||||
"net/url" // URL 解析
|
||||
"os" // 文件系统(静态文件读取)
|
||||
"regexp" // 正则表达式(site: 过滤语法)
|
||||
"sort" // 排序
|
||||
"strconv" // 字符串转整数
|
||||
@@ -69,7 +70,7 @@ func (s *Server) runPeriodicFlush() {
|
||||
// Flush 公开的刷盘方法,供定时任务和外部调用。
|
||||
func (s *Server) Flush() { s.flush() }
|
||||
|
||||
// Handler 返回 HTTP 路由处理器(统一端口,同时提供搜索和收获服务)。
|
||||
// Handler 返回 HTTP 路由处理器(统一端口,同时提供搜索、收获和静态文件服务)。
|
||||
func (s *Server) Handler() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
// 搜索路由
|
||||
@@ -83,9 +84,71 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("/admin/priority", s.handleAdminPriority)
|
||||
mux.HandleFunc("/admin/flush", s.handleAdminFlush)
|
||||
mux.HandleFunc("/admin/pending", s.handleAdminPending)
|
||||
// 静态文件(SPA fallback)
|
||||
mux.Handle("/", spaHandler{dist: "dist"})
|
||||
return mux
|
||||
}
|
||||
|
||||
// spaHandler 提供静态文件服务,并对非文件路径(如 /admin)返回 index.html(SPA 支持)。
|
||||
type spaHandler struct {
|
||||
dist string
|
||||
}
|
||||
|
||||
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Path
|
||||
|
||||
// API 路径(可能有后续处理)
|
||||
if strings.HasPrefix(path, "/search") ||
|
||||
strings.HasPrefix(path, "/admin") ||
|
||||
strings.HasPrefix(path, "/l") ||
|
||||
path == "/flush" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 去掉前缀斜杠
|
||||
staticPath := strings.TrimPrefix(path, "/")
|
||||
if staticPath == "" {
|
||||
staticPath = "index.html"
|
||||
}
|
||||
|
||||
// 尝试直接文件
|
||||
if data, err := os.ReadFile(h.dist + "/" + staticPath); err == nil {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
ext := strings.ToLower(path[strings.LastIndex(path, ".")+1:])
|
||||
switch ext {
|
||||
case "js":
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
case "css":
|
||||
w.Header().Set("Content-Type", "text/css")
|
||||
case "svg":
|
||||
w.Header().Set("Content-Type", "image/svg+xml")
|
||||
case "html":
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
case "png", "jpg", "jpeg", "gif", "ico", "webp":
|
||||
w.Header().Set("Content-Type", "image/"+ext)
|
||||
}
|
||||
w.Write(data)
|
||||
return
|
||||
}
|
||||
|
||||
// 如果路径包含文件扩展名但文件不存在,返回 404
|
||||
if strings.Contains(staticPath, ".") {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// SPA fallback:返回 index.html
|
||||
if data, err := os.ReadFile(h.dist + "/index.html"); err == nil {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Write(data)
|
||||
return
|
||||
}
|
||||
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
// ListenAndServe 启动搜索服务器。
|
||||
func (s *Server) ListenAndServe(addr string) error {
|
||||
log.Printf("[search] listening on %s", addr)
|
||||
|
||||
Reference in New Issue
Block a user