HTTP Middleware
Responsibility
internal/http/middleware/middleware.go provides four cross-cutting concerns applied
to every request in both the control plane backend and the frontend gateway:
request identity, panic recovery, structured access logging, and Prometheus
metrics. Ordering is defined in internal/http/router.go (backend) and
internal/web/server.go (frontend).
Chain order (outermost → innermost)
RequestID— assigns/propagatesX-Request-ID.Recovery— catches panics, logs them, returns 500.Logging— emits one slog line per request with method, path, status, duration, request id, remote.Metrics— incrementsflaggo_http_requests_totaland observesflaggo_http_request_duration_seconds.- mux (handlers).
Request ID propagation
RequestIDreadsX-Request-IDfrom the incoming request; if absent it generates 16 random hex bytes.- The id is stored in the request context (
requestIDKey) and echoed on the response header. RequestIDFromContextexposes it to handlers and downstream calls.- The frontend gateway sets
X-Request-IDon the proxied request to the backend, so a dashboard action correlates across both services. The backend's echoed copy is stripped byModifyResponseto avoid duplicate headers.
Recovery
Recovery wraps the handler in a deferred recover. On panic it logs the panic
value, path, and request id, then writes 500 Internal Server Error. This
prevents a single handler panic from crashing the process.
Logging
Logging wraps the response writer to capture the status code, records start
time, and emits one slog.Info("request", ...) line after the handler returns,
including duration in milliseconds.
Metrics
Metrics records per-request counters and histograms using
observability.Metrics (flaggo_http_requests_total,
flaggo_http_request_duration_seconds), labeled by method, path, and status.
The /metrics scrape endpoint is registered separately in the router.
Configuration
None. Middleware is always applied; metrics require a non-nil *observability.Metrics.
Representative tests
internal/web/server_test.go verifies gateway /healthz and /readyz
behavior; middleware ordering is exercised indirectly by handler tests.
See openwiki/testing/test-strategy.md.