package httpx import ( "net/http" "github.com/gin-gonic/gin" "senlinai-agent/backend/internal/config" "senlinai-agent/backend/internal/logic/auth" ) type RouteRegistrar interface { Register(router gin.IRouter) } func NewRouter(cfg config.Config, registrars ...RouteRegistrar) *gin.Engine { return newRouter(cfg, nil, registrars...) } func NewProtectedRouter(cfg config.Config, tokenVerifier func(string) (uint, error), registrars ...RouteRegistrar) *gin.Engine { return newRouter(cfg, tokenVerifier, registrars...) } func newRouter(cfg config.Config, tokenVerifier func(string) (uint, error), registrars ...RouteRegistrar) *gin.Engine { if cfg.Env == "test" { gin.SetMode(gin.TestMode) } router := gin.New() router.Use(gin.Recovery()) router.Use(cors()) router.GET("/healthz", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok"}) }) api := router.Group("/api") if tokenVerifier != nil { api.Use(auth.RequireUser(tokenVerifier)) } for _, registrar := range registrars { registrar.Register(api) } return router } func cors() gin.HandlerFunc { allowedOrigins := map[string]bool{ "http://localhost:5173": true, "http://127.0.0.1:5173": true, "http://localhost:4173": true, "http://127.0.0.1:4173": true, "http://localhost:4174": true, "http://127.0.0.1:4174": true, "http://localhost:4175": true, "http://127.0.0.1:4175": true, "http://tauri.localhost": true, } return func(c *gin.Context) { origin := c.GetHeader("Origin") if allowedOrigins[origin] { c.Header("Access-Control-Allow-Origin", origin) c.Header("Vary", "Origin") c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") c.Header("Access-Control-Allow-Headers", "Authorization, Content-Type") c.Header("Access-Control-Max-Age", "86400") } if c.Request.Method == http.MethodOptions { c.AbortWithStatus(http.StatusNoContent) return } c.Next() } }