package main import ( "context" "fmt" "net/http" "os" "os/signal" "time" "synlotto-website/bootstrap" "synlotto-website/config" "synlotto-website/handlers" "synlotto-website/logging" "synlotto-website/middleware" "synlotto-website/models" "synlotto-website/routes" "synlotto-website/storage" ) func main() { appState, err := bootstrap.LoadAppState("config/config.json") if err != nil { logging.Error("Failed to load app state: %v", err) } config.Init(appState.Config) logging.LogConfig(appState.Config) db := storage.InitDB("synlotto.db") models.SetDB(db) // Should be in storage not models. err = bootstrap.InitSession(appState.Config) if err != nil { logging.Error("❌ Failed to init session: %v", err) } err = bootstrap.InitCSRFProtection([]byte(appState.Config.CSRF.CSRFKey), appState.Config.HttpServer.ProductionMode) if err != nil { logging.Error("Failed to init CSRF: %v", err) } mux := http.NewServeMux() routes.SetupAdminRoutes(mux, db) routes.SetupAccountRoutes(mux, db) routes.SetupResultRoutes(mux, db) routes.SetupSyndicateRoutes(mux, db) mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) mux.HandleFunc("/", handlers.Home(db)) wrapped := bootstrap.CSRFMiddleware(mux) wrapped = middleware.RateLimit(wrapped) wrapped = middleware.EnforceHTTPS(wrapped, appState.Config.HttpServer.ProductionMode) wrapped = middleware.SecureHeaders(wrapped) wrapped = middleware.Recover(wrapped) addr := fmt.Sprintf("%s:%d", appState.Config.HttpServer.Address, appState.Config.HttpServer.Port) srv := &http.Server{ Addr: addr, Handler: wrapped, } go func() { logging.Info("Server running at %s\n", addr) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logging.Error("Server error: %v", err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit logging.Info("Shutting down server...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { logging.Error("Forced shutdown: %v", err) } logging.Info("Server shutdown complete") }