package router import ( "net/http" "mengyamonitor-backend-server/internal/config" "mengyamonitor-backend-server/internal/handler" "mengyamonitor-backend-server/internal/hub" "mengyamonitor-backend-server/internal/middleware" "mengyamonitor-backend-server/internal/store" "github.com/gin-gonic/gin" ) func New(cfg *config.Config, st *store.Store, h *hub.Hub) *gin.Engine { gin.SetMode(gin.ReleaseMode) r := gin.New() r.Use(gin.Logger(), gin.Recovery()) // 公网宽松 CORS:任意 Origin + 透传浏览器请求的 Header(预检) r.Use(func(c *gin.Context) { h := c.Writer.Header() origin := c.GetHeader("Origin") if origin != "" { h.Set("Access-Control-Allow-Origin", origin) h.Set("Access-Control-Allow-Credentials", "true") } else { h.Set("Access-Control-Allow-Origin", "*") } h.Set("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS") if reqH := c.GetHeader("Access-Control-Request-Headers"); reqH != "" { h.Set("Access-Control-Allow-Headers", reqH) } else { h.Set("Access-Control-Allow-Headers", "Content-Type, X-Admin-Token, Authorization, Accept, Origin, X-Requested-With") } h.Set("Access-Control-Max-Age", "86400") if c.Request.Method == http.MethodOptions { c.AbortWithStatus(http.StatusNoContent) return } c.Next() }) pub := &handler.Public{Store: st} r.GET("/", pub.Root) r.GET("/api/health", pub.Health) r.GET("/api/servers", pub.ListServers) r.GET("/api/ws/monitor", handler.MonitorWebSocket(h)) adm := &handler.Admin{Store: st, Cfg: cfg} r.POST("/api/admin/auth", adm.Auth) adminG := r.Group("/api/admin") adminG.Use(middleware.AdminToken(cfg)) { adminG.GET("/servers", adm.ListServers) adminG.POST("/servers", adm.CreateServer) adminG.PUT("/servers/reorder", adm.Reorder) adminG.PUT("/servers/:id", adm.UpdateServer) adminG.DELETE("/servers/:id", adm.DeleteServer) } r.NoRoute(func(c *gin.Context) { c.JSON(http.StatusNotFound, gin.H{ "error": "not_found", "path": c.Request.URL.Path, "method": c.Request.Method, }) }) return r }