package server import ( "context" "net/http" "strconv" "time" "github.com/gin-gonic/gin" "autostore/internal/application/interfaces" "autostore/internal/presentation/controllers" "autostore/internal/presentation/middleware" ) type Server struct { config *Config logger interfaces.ILogger itemsCtrl *controllers.ItemsController authCtrl *controllers.AuthController jwtMiddleware *middleware.JWTMiddleware httpServer *http.Server } type Config struct { Port int ReadTimeout time.Duration WriteTimeout time.Duration ShutdownTimeout time.Duration } func NewServer( config *Config, logger interfaces.ILogger, itemsCtrl *controllers.ItemsController, authCtrl *controllers.AuthController, jwtMiddleware *middleware.JWTMiddleware, ) *Server { return &Server{ config: config, logger: logger, itemsCtrl: itemsCtrl, authCtrl: authCtrl, jwtMiddleware: jwtMiddleware, } } func (s *Server) Start() error { gin.SetMode(gin.ReleaseMode) router := s.SetupRoutes() s.httpServer = &http.Server{ Addr: ":" + strconv.Itoa(s.config.Port), Handler: router, ReadTimeout: s.config.ReadTimeout, WriteTimeout: s.config.WriteTimeout, } s.logger.Info(context.Background(), "Server starting on port %d", s.config.Port) return s.httpServer.ListenAndServe() } func (s *Server) Shutdown(ctx context.Context) error { s.logger.Info(ctx, "Server shutting down") shutdownCtx, cancel := context.WithTimeout(ctx, s.config.ShutdownTimeout) defer cancel() return s.httpServer.Shutdown(shutdownCtx) } func (s *Server) SetupRoutes() *gin.Engine { router := gin.New() // Middleware router.Use(gin.Recovery()) router.Use(s.corsMiddleware()) // Health check router.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok"}) }) // API v1 group v1 := router.Group("/api/v1") // Auth routes (no JWT middleware) v1.POST("/login", s.authCtrl.Login) // Items routes (with JWT middleware) items := v1.Group("/items") items.Use(s.jwtMiddleware.Middleware()) { items.POST("", s.itemsCtrl.CreateItem) items.GET("", s.itemsCtrl.ListItems) items.GET("/:id", s.itemsCtrl.GetItem) items.DELETE("/:id", s.itemsCtrl.DeleteItem) } return router } func (s *Server) corsMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Credentials", "true") c.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Header("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204) return } c.Next() } }