package handler import ( "context" "fmt" "net/http" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" "uzdb/internal/config" "uzdb/internal/middleware" "uzdb/internal/services" ) // HTTPServer represents the HTTP API server type HTTPServer struct { engine *gin.Engine server *http.Server } // NewHTTPServer creates a new HTTP server func NewHTTPServer( connectionSvc *services.ConnectionService, querySvc *services.QueryService, ) *HTTPServer { // Set Gin mode based on environment cfg := config.Get() if cfg.IsProduction() { gin.SetMode(gin.ReleaseMode) } engine := gin.New() // Create handlers connectionHandler := NewConnectionHandler(connectionSvc) queryHandler := NewQueryHandler(connectionSvc, querySvc) // Setup middleware engine.Use(middleware.RecoveryMiddleware()) engine.Use(middleware.LoggerMiddleware()) engine.Use(middleware.CORSMiddleware()) engine.Use(middleware.SecureHeadersMiddleware()) // Setup routes api := engine.Group("/api") { connectionHandler.RegisterRoutes(api) queryHandler.RegisterRoutes(api) } // Health check endpoint engine.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "ok", "timestamp": time.Now().Format(time.RFC3339), }) }) return &HTTPServer{ engine: engine, } } // Start starts the HTTP server func (s *HTTPServer) Start(port string) error { s.server = &http.Server{ Addr: ":" + port, Handler: s.engine, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } config.GetLogger().Info("starting HTTP API server", zap.String("port", port)) if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { return fmt.Errorf("failed to start HTTP server: %w", err) } return nil } // Shutdown gracefully shuts down the HTTP server func (s *HTTPServer) Shutdown(ctx context.Context) error { if s.server == nil { return nil } config.GetLogger().Info("shutting down HTTP server") return s.server.Shutdown(ctx) }