Add production-ready HTTP server package with routing, health checks, and middleware

Introduces server/ sub-package as the server-side companion to the existing Client.
Includes Router (over http.ServeMux with groups and mounting), graceful shutdown with
signal handling, health endpoints (/healthz, /readyz), and built-in middlewares
(RequestID, Recovery, Logging). Zero external dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 13:41:54 +03:00
parent 6b901c931e
commit cea75d198b
12 changed files with 1215 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
package server
import (
"log/slog"
"net/http"
"time"
)
// Logging returns a middleware that logs each request's method, path,
// status code, duration, and request ID using the provided structured logger.
func Logging(logger *slog.Logger) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
sw := &statusWriter{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(sw, r)
duration := time.Since(start)
attrs := []slog.Attr{
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.Int("status", sw.status),
slog.Duration("duration", duration),
}
if id := RequestIDFromContext(r.Context()); id != "" {
attrs = append(attrs, slog.String("request_id", id))
}
level := slog.LevelInfo
if sw.status >= http.StatusInternalServerError {
level = slog.LevelError
}
logger.LogAttrs(r.Context(), level, "request completed", attrs...)
})
}
}