Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

117 lines
2.8 KiB

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()
}
}