package api import ( "net/http" "api-soap-facturacion/internal/config" "api-soap-facturacion/internal/logger" "api-soap-facturacion/internal/soap" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/jmoiron/sqlx" ) // NewRouter configura el router HTTP func NewRouter(cfg *config.Config, log logger.Logger, db *sqlx.DB, soapClients *soap.Clients) *gin.Engine { // Configurar modo de Gin según entorno if cfg.App.Environment == "production" { gin.SetMode(gin.ReleaseMode) } // Crear router router := gin.New() // Configurar middleware router.Use(gin.Recovery()) router.Use(LoggerMiddleware(log)) router.Use(RequestIDMiddleware()) router.Use(CORSMiddleware()) // Configurar manejadores handler := NewHandler(cfg, log, db, soapClients) // Rutas de salud router.GET("/health", handler.HealthCheck) // Rutas API api := router.Group("/api/v1") { // API1 api1 := api.Group("/api1") { api1.POST("/get-data", handler.API1GetData) } // API2 api2 := api.Group("/api2") { api2.POST("/process-transaction", handler.API2ProcessTransaction) } // Parámetros params := api.Group("/parameters") { params.GET("", handler.GetAllParameters) params.GET("/:key", handler.GetParameter) params.PUT("/:key", handler.UpdateParameter) } } return router } // LoggerMiddleware configura el middleware de logging func LoggerMiddleware(log logger.Logger) gin.HandlerFunc { return func(c *gin.Context) { // Antes de la solicitud path := c.Request.URL.Path method := c.Request.Method requestID := c.GetHeader("X-Request-ID") // Crear logger para esta solicitud reqLogger := log.With( logger.NewField("request_id", requestID), logger.NewField("path", path), logger.NewField("method", method), ) // Almacenar logger en el contexto c.Set("logger", reqLogger) reqLogger.Info("Solicitud iniciada") // Procesar solicitud c.Next() // Después de la solicitud status := c.Writer.Status() reqLogger.Info("Solicitud completada", logger.NewField("status", status), ) } } // RequestIDMiddleware genera un ID único para cada solicitud func RequestIDMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Si no hay ID de solicitud, generar uno requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = generateRequestID() c.Request.Header.Set("X-Request-ID", requestID) } // Establecer ID de solicitud en la respuesta c.Writer.Header().Set("X-Request-ID", requestID) c.Next() } } // CORSMiddleware configura CORS func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Request-ID") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusOK) return } c.Next() } } // generateRequestID genera un ID único para una solicitud func generateRequestID() string { return "req-" + uuid.New().String() }