// Package server initializes and runs the application server. // It sets up configurations, initializes the database, services, and controllers, // loads HTML templates, and starts the HTTP server. package server import ( "context" "net/http" "path/filepath" "time" "GoMembership/internal/config" "GoMembership/internal/controllers" "GoMembership/internal/middlewares" "GoMembership/internal/repositories" "GoMembership/internal/routes" "GoMembership/internal/services" "GoMembership/pkg/logger" "github.com/gin-gonic/gin" ) var shutdownChannel = make(chan struct{}) var srv *http.Server // Run initializes the server configuration, sets up services and controllers, and starts the HTTP server. func Run() { emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password) var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{} consentService := &services.ConsentService{Repo: consentRepo} var bankAccountRepo repositories.BankAccountRepositoryInterface = &repositories.BankAccountRepository{} bankAccountService := &services.BankAccountService{Repo: bankAccountRepo} var membershipRepo repositories.MembershipRepositoryInterface = &repositories.MembershipRepository{} var subscriptionRepo repositories.SubscriptionModelsRepositoryInterface = &repositories.SubscriptionModelsRepository{} membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo} var userRepo repositories.UserRepositoryInterface = &repositories.UserRepository{} var licenceRepo repositories.DriversLicenceInterface = &repositories.DriversLicenceRepository{} userService := &services.UserService{Repo: userRepo, Licences: licenceRepo} userController := &controllers.UserController{Service: userService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService} membershipController := &controllers.MembershipController{Service: *membershipService} contactController := &controllers.ContactController{EmailService: emailService} router := gin.Default() // gin.SetMode(gin.ReleaseMode) router.Static(config.Templates.StaticPath, "./style") // Load HTML templates router.LoadHTMLGlob(filepath.Join(config.Templates.HTMLPath, "*")) router.Use(gin.Logger()) router.Use(middlewares.CORSMiddleware()) router.Use(middlewares.CSPMiddleware()) router.Use(middlewares.SecurityHeadersMiddleware()) limiter := middlewares.NewIPRateLimiter(config.Security.Ratelimits.Limit, config.Security.Ratelimits.Burst) router.Use(middlewares.RateLimitMiddleware(limiter)) routes.RegisterRoutes(router, userController, membershipController, contactController) logger.Info.Println("Starting server on :8080") srv = &http.Server{ Addr: ":8080", Handler: router, } go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Error.Fatalf("could not start server: %v", err) } }() // Wait for the shutdown signal <-shutdownChannel } func Shutdown(ctx context.Context) error { if srv == nil { return nil } // Graceful shutdown with a timeout shutdownCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() // Attempt to shutdown the server return srv.Shutdown(shutdownCtx) }