Skip to main content
Middleware in Platforma wraps HTTP handlers to add cross-cutting concerns like authentication, logging, tracing, and request validation.

Middleware Interface

From httpserver/middleware.go:9, middleware implements a simple interface:
Any type with a Wrap method can be used as middleware.

MiddlewareFunc

For simple middleware, use the MiddlewareFunc convenience type from httpserver/middleware.go:15:
This lets you pass functions directly as middleware:

Creating Middleware

Basic Pattern

Middleware follows this structure:

Example: Request Logging

From demo-app/cmd/api/main.go:45, inline middleware for logging:

Example: TraceID Middleware

Real implementation from log/traceid.go:11:
Usage from demo-app/cmd/api/main.go:34:
This middleware generates a unique trace ID for each request, adds it to the response headers, and makes it available in the request context for logging.

Applying Middleware

Use() - Apply Middleware

From httpserver/handlergroup.go:19, apply middleware to a server or group:

UseFunc() - Apply Function Middleware

From httpserver/handlergroup.go:24, for inline middleware:

Wrap() - Apply to Single Handler

From auth/domain.go:27, wrap individual handlers:

Middleware Execution Order

Middleware is applied in reverse order from httpserver/middleware.go:26:
The first registered middleware is the outermost wrapper.
Example:
Execution flow:
  1. Request enters traceIDMiddleware
  2. Passes to loggingMiddleware
  3. Passes to authMiddleware
  4. Reaches handler
  5. Response flows back through auth → logging → traceID

Common Middleware Patterns

Authentication

Check for valid credentials and inject user into context:

Request Timing

Measure request duration:

Error Recovery

Recover from panics:

CORS Headers

Add cross-origin resource sharing headers:

Request ID Injection

Similar to TraceID, but from header if present:

Middleware with Configuration

Create configurable middleware using constructors:
Usage:

Context-Based Middleware

Pass values through request context:

Conditional Middleware

Apply middleware based on conditions:

Combining Middleware

Chain multiple middleware together:

Testing Middleware

Test middleware in isolation:

Best Practices

Place middleware that sets context values (like trace ID, user) before middleware that uses those values (like logging).
Unless you’re intentionally short-circuiting the request (auth failure, rate limit), always call h.ServeHTTP(w, r).
Reading r.Body consumes it. If you need to inspect the body, create a copy first using io.TeeReader.
Each middleware should do one thing well. Compose multiple middleware instead of creating monolithic ones.
Create a struct type for middleware with configuration rather than passing many parameters.

Next Steps

HTTP Routing

Learn how to apply middleware to routes and groups

Domains

See how middleware fits into domain architecture

Logging

Use context-aware logging in middleware