Files
wk-backend/internal/router/router.go
zhilv 2a6732ffe7 fix: 修复6个bug并接入CodeStable工作流
Bug修复:
- GetWorkList 使用了错误的 RecordType (RecordStudy→RecordWork)
- AllRecord handler 返回错误的分页信息 (page硬编码1, pageSize用RecordsCount)
- CourseParse creditNode nil panic (加nil检查)
- WebSocket CheckOrigin 安全漏洞 (release模式限制为同源)
- math/rand 可预测 (替换为 crypto/rand)
- GetDiscussList 未实现 (补全实现, 移除重复路由)

其他:
- 接入 CodeStable 工作流体系 (codestable/ 骨架 + AGENTS.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-25 19:55:57 +08:00

112 lines
2.6 KiB
Go

package router
import (
"ckwk/internal/conf"
"ckwk/internal/handler"
"ckwk/internal/middleware"
"ckwk/pkg/log"
"ckwk/web"
"io/fs"
"net/http"
"strings"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
var (
AllowOrigins []string
AllowMethods []string
AllowHeaders []string
)
func init() {
if conf.IsBuildDebugMode() {
AllowOrigins = []string{"*"}
AllowMethods = []string{"*"}
AllowHeaders = []string{"*"}
gin.SetMode(gin.DebugMode)
} else {
AllowOrigins = []string{"*.kmux.cn"}
AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "PATCH"}
AllowHeaders = []string{"X-Session-Id"}
gin.SetMode(gin.ReleaseMode)
}
}
func SetupRouter() *gin.Engine {
r := gin.Default()
r.Use(cors.New(cors.Config{
AllowOrigins: AllowOrigins,
AllowMethods: AllowMethods,
AllowHeaders: AllowHeaders,
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
r.Use(middleware.DebugHTTPLog())
wkHandler := handler.NewWKHandler()
sessionMiddleware := middleware.SessionMiddleware(wkHandler.Session)
// schedule.StartCron(wkHandler.Session)
dist, err := fs.Sub(web.Public, web.DistDir)
if err != nil {
log.Fatal("failed to read dist dir", zap.Error(err))
}
distHTTP := http.FS(dist)
r.StaticFS("/js", http.FS(mustSub(dist, "js")))
r.StaticFS("/assets", http.FS(mustSub(dist, "assets")))
r.StaticFileFS("/favicon.png", "favicon.png", distHTTP)
api := r.Group("/api")
{
api.POST("/login", wkHandler.Login)
api.Any("/version", handler.Version)
debug := api.Group("/debug")
{
debug.GET("/config", handler.DebugConfig)
debug.POST("/config", handler.UpdateDebugConfig)
debug.GET("/logs", handler.DebugLogs)
debug.GET("/logs/download", handler.DebugLogsDownload)
debug.GET("/logs/ws", handler.DebugLogWS)
}
v1 := api.Group("/v1")
{
v1.GET("/host", wkHandler.Host)
}
v2 := api.Group("/v2", sessionMiddleware)
{
v2.POST("/logout", wkHandler.Logout)
v2.POST("/userinfo", wkHandler.UserInfo)
v2.POST("/course", wkHandler.Course)
v2.POST("/study", wkHandler.Study)
v2.POST("/record", wkHandler.AllRecord)
}
}
r.NoRoute(func(ctx *gin.Context) {
if strings.HasPrefix(ctx.Request.URL.Path, "/api") {
ctx.JSON(404, gin.H{"code": 404, "msg": "API not found"})
return
}
ctx.Header("Content-Type", "text/html; charset=utf-8")
http.ServeFileFS(ctx.Writer, ctx.Request, dist, "index.html")
})
return r
}
// 辅助函数:简化 fs.Sub 的错误处理
func mustSub(f fs.FS, dir string) fs.FS {
sub, err := fs.Sub(f, dir)
if err != nil {
panic("failed to find static dir: " + dir)
}
return sub
}