package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/gin-gonic/gin" "github.com/joho/godotenv" "go.uber.org/zap" "veza-backend-api/internal/api" "veza-backend-api/internal/config" _ "veza-backend-api/docs" // Import docs for swagger ) // @title Veza Backend API // @version 1.2.0 // @description Backend API for Veza platform. // @termsOfService http://swagger.io/terms/ // @contact.name API Support // @contact.url http://www.veza.app/support // @contact.email support@veza.app // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host localhost:8080 // @BasePath /api/v1 // @securityDefinitions.apikey BearerAuth // @in header // @name Authorization func main() { // Charger les variables d'environnement if err := godotenv.Load(); err != nil { log.Printf("ℹ️ Note: Fichier .env non trouvé, utilisation des variables d'environnement système") } // Configuration du logger logger, err := zap.NewProduction() if err != nil { log.Fatalf("Impossible d'initialiser le logger: %v", err) } defer logger.Sync() logger.Info("🚀 Démarrage de Veza Backend API") // Charger la configuration cfg, err := config.NewConfig() if err != nil { logger.Fatal("❌ Impossible de charger la configuration", zap.Error(err)) } // Valider la configuration if err := cfg.Validate(); err != nil { logger.Fatal("❌ Configuration invalide", zap.Error(err)) } // Initialisation de la base de données db := cfg.Database if db == nil { logger.Fatal("❌ Base de données non initialisée") } defer db.Close() if err := db.Initialize(); err != nil { logger.Fatal("❌ Impossible d'initialiser la base de données", zap.Error(err)) } // Configuration du mode Gin // Correction: Utilisation directe de la variable d'env car non exposée dans Config appEnv := os.Getenv("APP_ENV") if appEnv == "production" { gin.SetMode(gin.ReleaseMode) } else { gin.SetMode(gin.DebugMode) } // Créer le router Gin router := gin.New() // Middleware globaux (Logger, Recovery) recommandés par ORIGIN router.Use(gin.Logger(), gin.Recovery()) // Configuration des routes apiRouter := api.NewAPIRouter(db, cfg) // Instantiate APIRouter apiRouter.Setup(router) // Call its Setup method // Configuration du serveur HTTP port := fmt.Sprintf("%d", cfg.AppPort) if cfg.AppPort == 0 { port = "8080" } server := &http.Server{ Addr: fmt.Sprintf(":%s", port), Handler: router, ReadTimeout: 30 * time.Second, // Standards ORIGIN WriteTimeout: 30 * time.Second, } // Gestion de l'arrêt gracieux quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) go func() { logger.Info("🌐 Serveur HTTP démarré", zap.String("port", port)) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("❌ Erreur du serveur HTTP", zap.Error(err)) } }() <-quit logger.Info("🔄 Arrêt du serveur...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { logger.Error("❌ Erreur lors de l'arrêt", zap.Error(err)) } else { logger.Info("✅ Serveur arrêté proprement") } }