middleware

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package middleware is the request-scoped plumbing every route needs before any handler runs: identity on the context, a trace id, a recovered panic, a deadline.

Order is not a style choice here. RequestID must precede Recover so a panic is logged with the id the client was given; Recover must precede everything that can panic; Timeout must precede the handler, not the logging. Chain gives you the order that is correct, and is what you should use unless you know why you are deviating.

Index

Constants

View Source
const HeaderRequestID = "X-Request-Id"

HeaderRequestID is the inbound/outbound correlation header.

View Source
const HeaderTraceID = "X-Trace-Id"

HeaderTraceID is the header a client quotes in a support ticket.

Variables

This section is empty.

Functions

func AccessLog

func AccessLog(opt AccessLogOptions) fiber.Handler

AccessLog writes one line per request that failed, was slow, or — when LogSuccess is set — per request at all.

func CORS

func CORS(opt CORSOptions) fiber.Handler

CORS answers preflights and sets the cross-origin headers.

It echoes the matched origin rather than sending the configured list, and sets Vary: Origin, so a shared cache cannot serve one tenant's origin header to another's browser.

func Chain

func Chain(opt ChainOptions) []fiber.Handler

Chain returns the standard middleware stack in the order that is correct.

RequestID first so everything after it can log the id. Recover second so a panic anywhere below is caught WITH that id. Headers and logging next. Identity before Timeout, so an authentication failure is not reported as a timeout. The handler last.

func Identity

func Identity(resolve IdentityResolver) fiber.Handler

Identity puts the tenant and actor on the Go context, where every layer below reads them from.

It does NOT decide whether the request is allowed — that is a guard's job. Keeping the two apart is what lets an endpoint be public and still know who the caller is when they happen to be signed in.

func RateLimit

func RateLimit(opt RateLimitOptions) fiber.Handler

RateLimit refuses callers over their budget with 429 and the standard RateLimit-* headers so a well-behaved client can back off instead of hammering.

func Recover

func Recover() fiber.Handler

Recover turns a panic into a 500 in the standard envelope, with the stack in the log and nothing of it on the wire.

A panic that escapes to Fiber's own recovery loses the trace id and the request context, which is exactly the information the incident needs.

func RequestID

func RequestID() fiber.Handler

RequestID establishes the correlation id for the request and puts it on the Fiber locals, on the Go context and on the response.

It TRUSTS an inbound X-Request-Id, which is what makes a trace span a gateway, a service and a worker. That trust is only safe behind your own edge: a public listener should strip the header there, or this becomes a log-injection vector.

func SecureHeaders

func SecureHeaders(opt SecureHeadersOptions) fiber.Handler

SecureHeaders sets the response headers that cost nothing and close a category of attack each.

func Timeout

func Timeout(d time.Duration) fiber.Handler

Timeout bounds a handler.

It sets a deadline on the context; it cannot stop a handler that ignores it. That is a real limit, not an oversight — Go has no way to kill a goroutine — so the value of this middleware is entirely in handlers and drivers that honour ctx. Code that performs I/O without a context is the thing to fix.

Types

type AccessLogOptions

type AccessLogOptions struct {
	// SkipPaths are not logged. Put the health and metrics endpoints here:
	// a liveness probe every two seconds is 43,200 log lines a day saying
	// nothing happened.
	SkipPaths []string
	// SlowThreshold promotes a slow request to warn. Zero disables it.
	SlowThreshold time.Duration
	// LogSuccess logs 2xx and 3xx as well. Off by default — the access log of
	// a busy service is a metric, and metrics belong in a metrics system.
	LogSuccess bool
}

AccessLogOptions configures AccessLog.

type CORSOptions

type CORSOptions struct {
	// AllowOrigins is an explicit list. "*" is honoured ONLY when
	// AllowCredentials is false — the combination is forbidden by the spec and
	// browsers reject it, so this middleware refuses to emit it rather than
	// letting you ship a configuration that silently never works.
	AllowOrigins []string
	// AllowOriginFunc decides per request, for the wildcard-subdomain case.
	// It takes precedence over AllowOrigins.
	AllowOriginFunc  func(origin string) bool
	AllowMethods     []string
	AllowHeaders     []string
	ExposeHeaders    []string
	AllowCredentials bool
	MaxAge           time.Duration
}

CORSOptions configures CORS.

type ChainOptions

type ChainOptions struct {
	Timeout       time.Duration
	AccessLog     AccessLogOptions
	SecureHeaders *SecureHeadersOptions
	Identity      IdentityResolver
}

ChainOptions configures Chain.

type IdentityResolver

type IdentityResolver func(c fiber.Ctx) (ctxkit.Tenant, ctxkit.Actor, error)

IdentityResolver extracts the tenant and actor from a request. Return an error to refuse the request outright; return zero values to let it proceed anonymously and have a guard decide.

type MemoryRateLimitStore

type MemoryRateLimitStore struct {
	// contains filtered or unexported fields
}

MemoryRateLimitStore is a fixed-window counter in process memory.

It is correct for one instance and for development. It is NOT a distributed limiter: with N replicas the effective limit is N times the configured one, and the counts vanish on restart.

func NewMemoryRateLimitStore

func NewMemoryRateLimitStore() *MemoryRateLimitStore

NewMemoryRateLimitStore returns an in-process store.

func (*MemoryRateLimitStore) Incr

func (s *MemoryRateLimitStore) Incr(key string, window time.Duration) (int, time.Time, error)

Incr implements RateLimitStore.

type RateLimitOptions

type RateLimitOptions struct {
	// Max requests per Window. Zero disables the middleware entirely, which
	// is the honest behaviour for an unset config — better than a limit of
	// zero that refuses everything.
	Max    int
	Window time.Duration
	// KeyFunc identifies the caller. The default is the client IP, which is
	// the right default and the wrong one behind a proxy that does not set
	// X-Forwarded-For: everyone shares one key and one user exhausts it for
	// all. Prefer an account or api-key based function.
	KeyFunc func(c fiber.Ctx) string
	// Skip exempts a request — a health probe, an internal caller.
	Skip  func(c fiber.Ctx) bool
	Store RateLimitStore
	// FailOpen decides what happens when the store errors. True (the default)
	// serves the request: a Redis blip should not take the API down with it.
	// Set false where the limit protects something that must not be exceeded.
	FailOpen *bool
}

RateLimitOptions configures RateLimit.

type RateLimitStore

type RateLimitStore interface {
	// Incr adds one to key's count within window and returns the new count
	// and the time the window resets.
	Incr(key string, window time.Duration) (count int, resetAt time.Time, err error)
}

RateLimitStore counts requests per key. The in-process implementation below is correct for a single instance; behind more than one replica, back it with Redis so the limit is the limit rather than the limit times the replica count.

type SecureHeadersOptions

type SecureHeadersOptions struct {
	// HSTSMaxAge enables Strict-Transport-Security. Zero disables it — do not
	// send HSTS from a service reachable over plain HTTP in development, or a
	// developer's browser will pin localhost to HTTPS and they will lose an
	// afternoon to it.
	HSTSMaxAge time.Duration
	// ContentSecurityPolicy is sent verbatim when non-empty. The default below
	// suits a JSON API; a service that serves HTML needs its own.
	ContentSecurityPolicy string
	// FrameOptions defaults to DENY.
	FrameOptions string
}

SecureHeadersOptions configures SecureHeaders.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL