Documentation
¶
Index ¶
- func AccessLog(logger log.Logger) gin.HandlerFunc
- func Authn(parser TokenParser, resolver PrincipalResolver) gin.HandlerFunc
- func Authz(az authz.Authorizer) gin.HandlerFunc
- func CORS(opts ...CORSOption) gin.HandlerFunc
- func Logger(l log.Logger) gin.HandlerFunc
- func LoggerFrom(ctx context.Context) log.Logger
- func Metrics(reg prometheus.Registerer) gin.HandlerFunc
- func Recovery() gin.HandlerFunc
- func RequestID() gin.HandlerFunc
- func RequestIDFrom(ctx context.Context) string
- func Timeout(d time.Duration) gin.HandlerFunc
- func Tracing(serviceName string) gin.HandlerFunc
- type CORSOption
- type PrincipalResolver
- type TokenParser
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AccessLog ¶
func AccessLog(logger log.Logger) gin.HandlerFunc
AccessLog logs request method, path, status, and latency. When a tracing span is active, trace_id / span_id are attached so log entries correlate with the distributed trace.
func Authn ¶
func Authn(parser TokenParser, resolver PrincipalResolver) gin.HandlerFunc
Authn creates a Bearer-token authentication middleware.
parser: validates the token (built-in jwt.Manager or custom TokenParser). Panics if nil — configuration errors are caught at startup, not at request time. resolver: optional, enriches Principal from subject+claims.
func Authz ¶
func Authz(az authz.Authorizer) gin.HandlerFunc
Authz creates an authorization middleware.
It extracts the Principal from the request context (set by Authn), then calls az.Authorize with subject=Principal.Subject, object=route pattern, action=HTTP method.
Error semantics:
- Authorize returns error → infrastructure failure → log + 500.
- Authorize returns !allowed → policy denial → 403.
Panics if az is nil (configuration error caught at startup).
func Logger ¶
func Logger(l log.Logger) gin.HandlerFunc
Logger injects the given logger into the request context. The logger is enriched with the request's request_id (if present) so downstream code calling log.FromContext(ctx) gets structured per-request logging for free.
Both ctxval (internal, used by handler error logging) and log.WithContext (public, used by business code) are populated.
func LoggerFrom ¶
LoggerFrom extracts the logger from context (user-facing helper). Prefers log.FromContext (canonical path); falls back to ctxval for backward compatibility.
func Metrics ¶
func Metrics(reg prometheus.Registerer) gin.HandlerFunc
Metrics returns a gin middleware that instruments HTTP requests with the RED (Rate, Errors, Duration) metrics — the industry-standard golden signals for any HTTP service:
- http_requests_total{method, path, status} — counter
- http_request_duration_seconds{method, path} — histogram
- http_requests_in_flight — gauge
reg is typically obtained from MetricsComponent.PrometheusRegistry(). The middleware is safe to use with any prometheus.Registerer, and is idempotent across re-initialisation: on AlreadyRegisteredError (which happens when HTTPComponent.Init runs after a prior Init/Close cycle) the existing collectors are reused instead of panicking.
func Recovery ¶
func Recovery() gin.HandlerFunc
Recovery returns a middleware that recovers from panics and returns 500. The response uses handler.WriteResponse for format consistency with normal errors (code/reason/message/request_id). The panic and stack trace are logged via the context logger if available; if not (e.g. the panic fired before the Logger middleware ran), the trace is written to stderr so the incident is never silently swallowed.
func RequestID ¶
func RequestID() gin.HandlerFunc
RequestID generates or propagates a request ID via the X-Request-ID header. Client-supplied IDs are truncated to 128 chars and reduced to a strict ASCII safe-set ([A-Za-z0-9._-]) before propagation. The whitelist approach blocks log-injection vectors that the previous "strip < 0x20" filter missed: high-byte UTF-8 sequences such as U+2028 (LINE SEPARATOR) / U+2029 (PARAGRAPH SEPARATOR) used to be passed through verbatim and could split log lines in viewers that interpret them as breaks.
As a convenience, the resolved client IP (c.ClientIP()) is also stored in the request context so downstream handlers — in particular the account module's login rate limiter — can key on source address without needing direct access to *gin.Context.
func RequestIDFrom ¶
RequestIDFrom extracts the request ID from context (user-facing helper).
func Timeout ¶
func Timeout(d time.Duration) gin.HandlerFunc
Timeout returns a middleware that injects a context deadline into each request. Handlers (and libraries they call — DB drivers, HTTP clients) that respect context cancellation will stop work when the deadline fires, and the middleware writes a 504 if no response was produced.
A zero or negative duration disables the middleware (pass-through).
This is a cooperative timeout: the handler runs synchronously on the same goroutine, so gin.Context is never accessed concurrently. If a handler ignores context cancellation (e.g. a pure CPU loop), it will block until it returns on its own. For hard process-level limits, configure http.Server.WriteTimeout instead.
func Tracing ¶
func Tracing(serviceName string) gin.HandlerFunc
Tracing returns a middleware that creates a server span for each HTTP request using the global OpenTelemetry TracerProvider. Span name follows the OpenTelemetry HTTP semantic conventions: "METHOD route" (e.g. "GET /api/v1/posts/:id").
When the TracerProvider is a no-op (tracing disabled), the middleware adds negligible overhead — the span is never sampled and attributes are not recorded.
This middleware should be placed early in the chain (after Recovery, RequestID) so that downstream middleware and handlers inherit the span context. The Logger middleware will automatically pick up trace_id / span_id from the span context.
Types ¶
type CORSOption ¶
type CORSOption func(*corsConfig)
CORSOption configures the CORS middleware.
func WithAllowCredentials ¶
func WithAllowCredentials(allow bool) CORSOption
WithAllowCredentials enables Access-Control-Allow-Credentials: true, permitting browsers to send cookies / Authorization headers on cross- origin requests. Incompatible with a wildcard Origin — CORS() panics at setup time if both are configured, because the combination is a credential-leak vector (any origin could read authenticated responses).
func WithAllowHeaders ¶
func WithAllowHeaders(headers ...string) CORSOption
func WithAllowMethods ¶
func WithAllowMethods(methods ...string) CORSOption
func WithAllowOrigins ¶
func WithAllowOrigins(origins ...string) CORSOption
func WithExposeHeaders ¶
func WithExposeHeaders(headers ...string) CORSOption
WithExposeHeaders lists response headers that browsers should make visible to JavaScript. By default only simple headers are accessible to cross-origin fetchers; anything else (X-Request-ID, Retry-After, custom pagination cursors, etc.) needs explicit listing here or the client JS can't read them.
func WithMaxAge ¶
func WithMaxAge(seconds int) CORSOption
type PrincipalResolver ¶
type PrincipalResolver func(ctx context.Context, subject string, claims map[string]any) (auth.Principal, error)
PrincipalResolver builds a full Principal from the JWT subject and claims. Optional: when nil, the middleware constructs a minimal Principal from subject and claims only. Receives claims so that roles/tenant can be read directly from the token without an extra database lookup.
type TokenParser ¶
type TokenParser interface {
Parse(token string) (subject string, claims map[string]any, err error)
}
TokenParser parses a token string and returns the subject and claims. The built-in jwt.Manager implements this interface (HS256). Users needing RS256/EdDSA/external IdP can provide their own implementation.