package router import ( "github.com/gin-gonic/gin" "hy2xs-admin/dao" "hy2xs-admin/frontend" "hy2xs-admin/middleware" "hy2xs-admin/model/constant" "os" ) // Router собирает HTTP-контур админки. // // Панель всегда живёт в корне: настраиваемый web-контекст был возможностью H UI // разворачивать панель по произвольному пути, а HY2XS слушает только loopback // и отдаёт панель через SSH-туннель или reverse proxy. Настройка, которую UI // уже не позволял менять, а backend продолжал читать из SQLite, — это не // точка расширения, а лишний источник истины. func Router(router *gin.Engine) { router.GET("/healthz", func(c *gin.Context) { sqliteReady := dao.IsSqliteReady() configReadable := false if stat, err := os.Stat(constant.Hysteria2ConfigPath); err == nil { configReadable = !stat.IsDir() } if !sqliteReady || !configReadable { c.JSON(503, gin.H{ "ok": false, "service": "hy2xs-admin", "sqlite_ready": sqliteReady, "config_readable": configReadable, }) return } c.JSON(200, gin.H{ "ok": true, "service": "hy2xs-admin", "sqlite_ready": true, "config_readable": true, }) }) frontend.InitFrontend(router, "/") // Machine-контур. Не часть операторского API: это внутренний канал между // Hysteria и админкой, поэтому у него отдельное пространство имён, // собственный middleware и никакого JWT. machineAPI := router.Group(constant.HysteriaMachineAuthPath) machineAPI.Use(middleware.LocalOnlyHandler(), middleware.MachineAuthHandler(), middleware.LogHandler()) initHysteria2MachineAuthRouter(machineAPI) api := router.Group(constant.AdminAPIBase) authAPI := api.Group("") authAPI.Use(middleware.FilterHandler(), middleware.LogHandler(), middleware.RateLimiterHandler()) initAuthRouter(authAPI) adminAPI := api.Group("") adminAPI.Use( middleware.FilterHandler(), middleware.LogHandler(), middleware.RateLimiterHandler(), middleware.JWTHandler(), middleware.AdminHandler(), ) initAdminRouter(adminAPI) initDashboardRouter(adminAPI) initPeerRouter(adminAPI) initConfigRouter(adminAPI) initLogRouter(adminAPI) }