mw

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 29, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package mw provides transport-level HTTP middleware for Einherjar services.

All middleware functions return func(http.Handler) http.Handler and are composed via [server.WithMiddleware] or chi's Use method.

server.WithMiddleware(
    mw.Recover(),
    mw.RequestID(uuid.NewString),
    mw.RequestLogger(logger),
    mw.CORS([]string{"https://example.com"}),
)

Rate limiting

// In-memory (default — no extra dependencies)
store := mw.NewInMemoryRateLimiterStore(100, 20)
srv.Use(mw.IPRateLimit(store, logger))

// Distributed — swap store, middleware unchanged
store := valkeymw.NewRateLimiterStore(client, 100, 20)
srv.Use(mw.IPRateLimit(store, logger))

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CORS

func CORS(origins []string) func(http.Handler) http.Handler

CORS sets cross-origin resource sharing headers for the provided origins. Returns 204 No Content for OPTIONS preflight requests. Pass the outermost origins first; an empty slice is a no-op.

func CORSAllowAll

func CORSAllowAll() func(http.Handler) http.Handler

CORSAllowAll is a convenience wrapper that allows any origin. Use only in development — never in production.

func IPRateLimit

func IPRateLimit(store RateLimiterStore, logger logging.Logger) func(http.Handler) http.Handler

IPRateLimit returns middleware that rate-limits requests by client IP address. The IP is extracted from X-Forwarded-For (first value) or RemoteAddr. When the store returns an error the middleware fails open: the error is logged and the request is allowed through.

func Recover

func Recover(logger logging.Logger) func(http.Handler) http.Handler

Recover catches panics in downstream handlers, writes a 500 response, and logs the recovered value with a stack trace. Place it as the outermost middleware.

func RequestID

func RequestID(generator func() string) func(http.Handler) http.Handler

RequestID injects a unique request ID into the context (via logz.WithRequestID) and sets the X-Request-ID response header. generator is called once per request — pass uuid.NewString or a custom function.

func RequestLogger

func RequestLogger(logger logging.Logger) func(http.Handler) http.Handler

RequestLogger logs each request after the handler returns, including method, path, status code, and latency. Uses StatusRecorder to capture the status. Place after RequestID so the request ID is available in the log record.

func UserRateLimit

func UserRateLimit(store RateLimiterStore, logger logging.Logger) func(http.Handler) http.Handler

UserRateLimit returns middleware that rate-limits by authenticated user ID. Falls back to client IP when no security.Identity is present in the context. When the store returns an error the middleware fails open.

Types

type InMemoryRateLimiterStore

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

InMemoryRateLimiterStore is a per-key token-bucket rate limiter backed by an in-memory map. Suitable for single-instance deployments or development. For distributed rate limiting implement RateLimiterStore with a Valkey or Redis backend and pass it to IPRateLimit or UserRateLimit instead.

Stale entries are evicted every 5 minutes by a background goroutine. [Allow] always returns a nil error — in-memory never has infrastructure failures.

func NewInMemoryRateLimiterStore

func NewInMemoryRateLimiterStore(rps float64, burst int) *InMemoryRateLimiterStore

NewInMemoryRateLimiterStore creates a per-key token bucket store. rps is the sustained request rate per second per key. burst is the maximum instantaneous burst per key.

func (*InMemoryRateLimiterStore) Allow

Allow returns true when the request for key is within the configured rate limit.

type RateLimiterStore

type RateLimiterStore interface {
	// Allow returns true when the request for the given key is within the rate limit.
	// A non-nil error means the store is temporarily unavailable; middleware fails open.
	Allow(ctx context.Context, key string) (bool, error)
}

RateLimiterStore is the pluggable backend for rate-limiting middleware. The key is determined by the caller (client IP or user ID).

Shipped implementations:

  • InMemoryRateLimiterStore — per-key token bucket, stdlib only (this package)
  • einherjar/cache-valkey — Valkey-backed store for distributed deployments

cache-valkey satisfies this interface via Go duck typing — it never imports web/mw.

type StatusRecorder

type StatusRecorder struct {
	http.ResponseWriter
	Status int
}

StatusRecorder wraps http.ResponseWriter to capture the written status code. Used by RequestLogger to log the response status after the handler returns.

func (*StatusRecorder) WriteHeader

func (r *StatusRecorder) WriteHeader(code int)

WriteHeader captures the status code and delegates to the underlying writer.

Jump to

Keyboard shortcuts

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