Skip to main content

Middleware

Middleware in pb-ext allows you to intercept and modify requests/responses, enforce authentication, log requests, and implement cross-cutting concerns.

Middleware Patterns

pb-ext supports PocketBase’s middleware system with two binding methods:

.Bind() - Hook Middleware

Binds a middleware that implements hook.Handler[T]:
Characteristics:
  • Returns hook.Handler[T] (wraps the event)
  • Can short-circuit the chain by not calling e.Next()
  • Type-safe with generics

.BindFunc() - Function Middleware

Binds a plain function:
Characteristics:
  • Simpler syntax
  • No hook.Handler wrapper needed
  • Can access e.Router, e.App, e.Server

PocketBase Built-in Middleware

PocketBase provides several authentication middleware:

RequireAuth

Requires any authenticated user (user or admin):

RequireAdminAuth

Requires admin/superuser authentication:

RequireRecordAuth

Requires authenticated record from a specific collection:

RequireAdminOrRecordAuth

Requires either admin or record auth:

Chaining Middleware

Middleware can be chained using multiple .Bind() calls:
Execution order: Left-to-right (rate limit → auth → validate → handler)

Custom Middleware Examples

Request Logger Middleware

From cmd/server/routes.go:
Key Points:
  • Calls e.Next() to continue chain
  • Measures time before/after handler
  • Returns the error from e.Next()

Rate Limiting Middleware

Request ID Middleware

CORS Middleware

Validation Middleware

Error Recovery Middleware

Request Event Flow

The complete request flow with middleware: Example with multiple middleware layers:
Execution order:
  1. corsMiddleware (global)
  2. requestLoggerMW (route-specific)
  3. rateLimitMiddleware (route-specific)
  4. apis.RequireAuth() (route-specific)
  5. validateContentType (route-specific)
  6. createTodoHandler (handler)

Middleware with VersionedAPIRouter

When using pb-ext’s versioned router:

Context Values

Store and retrieve values in the request context:

Set Value in Middleware

Get Value in Handler

Best Practices

Call e.Next()

Always call e.Next() to continue the middleware chain, unless intentionally short-circuiting.

Order Matters

Place authentication middleware before authorization. Place logging middleware early to capture all requests.

Return Errors

Always return errors from middleware. Don’t silently swallow them.

Avoid Side Effects

Keep middleware focused. Avoid complex business logic in middleware.

Common Patterns

Conditional Middleware

Apply middleware only if a condition is met:

Middleware Factory

Create reusable middleware with configuration:

Response Transformation

Modify responses after handler execution:

Performance Considerations

Middleware Cost

Each middleware adds latency:
  • Auth check: ~1-5ms (database lookup)
  • Rate limiting: <1ms (in-memory check)
  • Logging: <1ms (async preferred)
  • Validation: ~1-10ms (depends on complexity)

Optimization Tips

  1. Cache auth results for repeated checks
  2. Use async logging to avoid blocking
  3. Skip middleware for health check endpoints
  4. Combine middleware when possible

Testing Middleware

Further Reading