package app import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "go-backend-template/config" "go-backend-template/internal/client" "go-backend-template/internal/handler" "go-backend-template/internal/router" "go-backend-template/internal/service" ) type App struct { server *http.Server router *router.Router shutdown chan os.Signal } func NewApp() *App { return &App{ shutdown: make(chan os.Signal, 1), } } func (a *App) Initialize(cfg *config.Config) error { healthHandler := handler.NewHealthHandler() dukcapilClient := client.NewDukcapilClient(cfg.Dukcapil) dukcapilService := service.NewDukcapilService(dukcapilClient) dukcapilHandler := handler.NewDukcapilHandler(dukcapilService, cfg) a.router = router.NewRouter( cfg, nil, // authHandler nil, // authMiddleware healthHandler, nil, // userHandler dukcapilHandler, ) return nil } func (a *App) Start(port string) error { engine := a.router.Init() // Debug: log what port value we received log.Printf("DEBUG: Received port value: %q", port) // Ensure proper address format // Only accept port number, not full addresses addr := ":" + port if port == "" { addr = ":8080" // default port } log.Printf("DEBUG: Final address: %q", addr) a.server = &http.Server{ Addr: addr, Handler: engine, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } signal.Notify(a.shutdown, os.Interrupt, syscall.SIGTERM) go func() { log.Printf("Server starting on port %s", port) if err := a.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Failed to start server: %v", err) } }() <-a.shutdown log.Println("Shutting down server...") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := a.server.Shutdown(ctx); err != nil { log.Printf("Server forced to shutdown: %v", err) return err } log.Println("Server exited gracefully") return nil } func (a *App) Shutdown() { close(a.shutdown) }