package api import ( "log" "github.com/gin-gonic/gin" "oci-portal/internal/service" ) // NewRouter 组装 HTTP 路由骨架:中间件链、公开/鉴权分组与各域注册; // 具体路由按域拆在 routes_*.go。/auth/login 公开,业务路由要求 JWT。 func NewRouter(auth *service.AuthService, oauth *service.OAuthService, ociConfigs *service.OciConfigService, tasks *service.TaskService, console *service.ConsoleService, settings *service.SettingService, notifier *service.Notifier, systemLogs *service.SystemLogService, logEvents *service.LogEventService, proxies *service.ProxyService, aiGateway *service.AiGatewayService) *gin.Engine { r := gin.New() // 禁用 gin 内置代理信任:真实 IP 统一由 RealIPMiddleware 按安全设置解析 _ = r.SetTrustedProxies(nil) registerWebhook(r, settings, logEvents) // 访问日志不落 query string:webconsole WS 的 JWT 经 query 传递,默认 Logger 会打进 stdout/journal accessLog := gin.LoggerWithConfig(gin.LoggerConfig{SkipQueryString: true}) r.Use(accessLog, RealIPMiddleware(settings), IPRateMiddleware(settings), gin.Recovery()) v1 := r.Group("/api/v1") registerAuthPublic(v1, auth, oauth, systemLogs) // AI 网关对外端点:独立密钥鉴权,挂在全局 Use 之后,仍受 IP 限速与 Recovery 保护 registerAiGateway(r, aiGateway) // 系统日志中间件挂在鉴权之后,写请求自动留痕(webconsole ws 为 GET,天然跳过) secured := v1.Group("", RequireAuth(auth), systemLogMiddleware(systemLogs)) registerAuthSecured(secured, auth, oauth, settings, systemLogs) registerConsole(v1, secured, console, auth) registerSettings(secured, settings, notifier, systemLogs, proxies) registerTasksAndLogs(secured, tasks, logEvents) registerOci(secured, ociConfigs) registerAiAdmin(secured, aiGateway) registerSwagger(r) // 嵌入的前端产物兜底伺服;失败仅降级为纯 API 服务,不阻塞启动 if err := registerWebUI(r); err != nil { log.Printf("[warn] webui disabled: %v", err) } return r } // registerWebhook 挂载 ONS 回传入口。必须注册在全局 Logger 之前: // 访问日志不落含 secret 的路径;不挂系统日志中间件——投递高频且已在回传日志留痕。 func registerWebhook(r *gin.Engine, settings *service.SettingService, logEvents *service.LogEventService) { wh := &webhookHandler{events: logEvents} r.POST("/api/v1/webhooks/oci-logs/:secret", gin.Recovery(), RealIPMiddleware(settings), wh.handle) }