package server import ( "context" "net/http" "DanceLessonsCoach/pkg/config" "DanceLessonsCoach/pkg/greet" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/rs/zerolog/log" ) type Server struct { router *chi.Mux readyCtx context.Context withOTEL bool } func NewServer(cfg *config.Config, readyCtx context.Context) *Server { s := &Server{ router: chi.NewRouter(), readyCtx: readyCtx, withOTEL: cfg.GetTelemetryEnabled(), } s.setupRoutes() return s } func (s *Server) setupRoutes() { // Use Zerolog middleware instead of Chi's default logger s.router.Use(middleware.RequestLogger(&middleware.DefaultLogFormatter{ Logger: &log.Logger, NoColor: false, })) // Health endpoint at root level s.router.Get("/api/health", s.handleHealth) // Readiness endpoint at root level s.router.Get("/api/ready", s.handleReadiness) // API routes s.router.Route("/api/v1", func(r chi.Router) { r.Use(s.getAllMiddlewares()...) s.registerApiV1Routes(r) }) } func (s *Server) registerApiV1Routes(r chi.Router) { greetService := greet.NewService() greetHandler := greet.NewApiV1GreetHandler(greetService) r.Route("/greet", func(r chi.Router) { greetHandler.RegisterRoutes(r) }) } // getAllMiddlewares returns all middleware including OpenTelemetry if enabled func (s *Server) getAllMiddlewares() []func(http.Handler) http.Handler { middlewares := []func(http.Handler) http.Handler{ middleware.StripSlashes, middleware.Recoverer, } if s.withOTEL { middlewares = append(middlewares, func(next http.Handler) http.Handler { return otelhttp.NewHandler(next, "") }) } return middlewares } func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { log.Info().Msg("Health check requested") w.Write([]byte(`{"status":"healthy"}`)) } func (s *Server) handleReadiness(w http.ResponseWriter, r *http.Request) { log.Info().Msg("Readiness check requested") select { case <-s.readyCtx.Done(): log.Info().Msg("Readiness check: not ready (shutting down)") w.WriteHeader(http.StatusServiceUnavailable) w.Write([]byte(`{"ready":false}`)) default: log.Info().Msg("Readiness check: ready") w.Write([]byte(`{"ready":true}`)) } } func (s *Server) Router() http.Handler { return s.router }