go-first/cmd/server/main.go

119 lines
2.7 KiB
Go
Raw Permalink Normal View History

2026-10-07 15:21:47 +02:00
package main
import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/dnoulet/go-first/internal/config"
"github.com/dnoulet/go-first/internal/handler"
"github.com/dnoulet/go-first/internal/middleware"
"github.com/dnoulet/go-first/internal/service"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
if err := godotenv.Load(); err != nil {
log.Info().Msg("No .env file found, using config.yaml")
}
cfg, err := config.Load("config.yaml")
if err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
setupLogging(cfg.Logging)
if cfg.Server.Mode == "release" {
gin.SetMode(gin.ReleaseMode)
}
router := setupRouter(cfg)
srv := &http.Server{
Addr: cfg.Server.Address(),
Handler: router,
ReadTimeout: cfg.Server.ReadTimeoutDuration(),
WriteTimeout: cfg.Server.WriteTimeoutDuration(),
IdleTimeout: cfg.Server.IdleTimeoutDuration(),
}
go func() {
log.Info().Str("address", cfg.Server.Address()).Msg("Starting server")
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal().Err(err).Msg("Failed to start server")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Info().Msg("Shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal().Err(err).Msg("Server forced to shutdown")
}
log.Info().Msg("Server exited")
}
func setupLogging(cfg config.LoggingConfig) {
level, err := zerolog.ParseLevel(cfg.Level)
if err != nil {
level = zerolog.InfoLevel
}
zerolog.SetGlobalLevel(level)
if cfg.Format == "console" || cfg.Output == "stdout" {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339})
}
}
func setupRouter(cfg *config.Config) *gin.Engine {
router := gin.New()
router.Use(middleware.Recovery())
router.Use(middleware.Logger())
router.Use(middleware.SecurityHeaders())
router.Use(middleware.CORS(cfg.CORS.AllowedOrigins))
skillService := service.NewSkillService()
projectService := service.NewProjectService()
experienceService := service.NewExperienceService()
serviceService := service.NewServiceService()
emailService := service.NewMockEmailService()
contactService := service.NewContactService(emailService)
h := handler.NewHandler(
skillService,
projectService,
experienceService,
serviceService,
contactService,
)
h.RegisterRoutes(router)
router.NoRoute(func(c *gin.Context) {
c.JSON(404, gin.H{
"success": false,
"error": gin.H{
"code": "NOT_FOUND",
"message": "Route not found",
},
})
})
return router
}