Files
stock-analysis/internal/router/router.go
WarrenZhou e28bfec957 Initial commit: 可转债轮动分析系统
- 实时行情:东财push2主源 + 腾讯批量报价备用源(自动切换)
- 历史K线:东财push2his主源 + 腾讯web子域备用源(含熔断机制)
- 增量同步:支持 -incr/-since 参数按存档日期增量入库
- 策略回测:净值曲线/10指标/基准对比,含基本面过滤
- 用户认证:用户名密码 + 邮箱验证码双登录方式
- 前端:三Tab SPA(实时行情/策略回测/数据管理)
2026-08-17 20:23:22 +08:00

72 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package router 负责 HTTP 路由注册,将请求分发到 Controller。
package router
import (
"fmt"
"net/http"
"path/filepath"
"strings"
"stock-analysis/internal/controller"
)
// New 构建应用路由处理器。
// webDir 为前端静态资源目录(View 层)。
func New(mc *controller.MarketController, ac *controller.AuthController, webDir string) http.Handler {
mux := http.NewServeMux()
// 公开接口:无需登录。
mux.HandleFunc("POST /api/auth/send-code", ac.SendCode)
mux.HandleFunc("POST /api/auth/register", ac.Register)
mux.HandleFunc("POST /api/auth/login", ac.Login)
// 受保护接口:需要登录。
mux.HandleFunc("GET /api/auth/me", ac.Me)
mux.HandleFunc("POST /api/auth/logout", ac.Logout)
mux.HandleFunc("GET /api/bonds", requireAuth(ac, mc.ListBonds))
mux.HandleFunc("GET /api/bonds/{code}/kline", requireAuth(ac, mc.GetKline))
mux.HandleFunc("POST /api/backtest", requireAuth(ac, mc.RunBacktest))
mux.HandleFunc("GET /api/status", requireAuth(ac, mc.GetDataStatus))
mux.HandleFunc("GET /api/db/bonds", requireAuth(ac, mc.ListDBBonds))
// 静态资源:登录页及样式脚本公开,首页受保护。
fs := noCache(http.FileServer(http.Dir(webDir)))
mux.Handle("/auth.html", fs)
mux.Handle("/style.css", fs)
mux.HandleFunc("/", requireAuth(ac, func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" && r.URL.Path != "/index.html" {
http.NotFound(w, r)
return
}
http.ServeFile(w, r, filepath.Join(webDir, "index.html"))
}))
return mux
}
// requireAuth 中间件:未登录的 API 请求返回 401,页面请求重定向到登录页。
func requireAuth(ac *controller.AuthController, next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if _, err := ac.CurrentUser(r); err != nil {
if strings.HasPrefix(r.URL.Path, "/api/") {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintf(w, `{"error":"%s"}`, err.Error())
} else {
http.Redirect(w, r, "/auth.html", http.StatusFound)
}
return
}
next.ServeHTTP(w, r)
}
}
// noCache 中间件:禁止浏览器缓存静态资源,确保每次加载最新版本。
func noCache(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
next.ServeHTTP(w, r)
})
}