Files
gitea-notification-hub/internal/server/server.go
T

98 lines
2.2 KiB
Go

package server
import (
"context"
"fmt"
"net/http"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/rs/zerolog"
"github.com/vincentc-afk/gitea-notification-hub/internal/config"
)
// Server represents the HTTP server
type Server struct {
cfg *config.Config
logger zerolog.Logger
router *chi.Mux
srv *http.Server
}
// New creates a new Server instance
func New(cfg *config.Config, logger zerolog.Logger) *Server {
r := chi.NewRouter()
// Middleware
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Recoverer)
r.Use(requestLogger(logger))
s := &Server{
cfg: cfg,
logger: logger,
router: r,
}
// Health check endpoint
r.Get("/health", s.handleHealth)
return s
}
// Router returns the chi router for registering additional routes
func (s *Server) Router() *chi.Mux {
return s.router
}
// Start starts the HTTP server
func (s *Server) Start() error {
addr := fmt.Sprintf(":%d", s.cfg.Server.Port)
s.srv = &http.Server{
Addr: addr,
Handler: s.router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
}
s.logger.Info().Str("addr", addr).Msg("starting HTTP server")
return s.srv.ListenAndServe()
}
// Shutdown gracefully shuts down the server
func (s *Server) Shutdown(ctx context.Context) error {
s.logger.Info().Msg("shutting down HTTP server")
return s.srv.Shutdown(ctx)
}
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok"}`))
}
// requestLogger returns a middleware that logs HTTP requests
func requestLogger(logger zerolog.Logger) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
defer func() {
logger.Info().
Str("method", r.Method).
Str("path", r.URL.Path).
Int("status", ww.Status()).
Dur("duration", time.Since(start)).
Msg("request")
}()
next.ServeHTTP(ww, r)
})
}
}