Middleware Overview
Spry keeps request behavior explicit.
Middleware is the layer for cross-cutting request logic such as:
- request IDs
- logging
- response timing
- header shaping
- auth guards
If a concern changes request flow across multiple handlers, it belongs in middleware.
If it converts thrown errors into responses, it belongs in _error.dart.
The contract
Spry middleware uses one small contract:
typedef Middleware = FutureOr<Response> Function(Event event, Next next);That means a middleware can:
- continue by calling
next() - stop the pipeline by returning a
Response
There is no extra hidden lifecycle around it.
Global and scoped middleware
Spry supports two places for middleware:
Global middleware
Files in top-level middleware/ apply across the app and are loaded in filename order.
middleware/
01_request_id.dart
02_logger.dart
03_auth.get.dartSpry also supports method-scoped global middleware. Add the HTTP method before .dart to apply a middleware only to that request method:
middleware/03_auth.get.dartmiddleware/04_write_audit.post.dart
Supported method suffixes are: get, post, put, patch, delete, head, and options.
Scoped middleware
Use _middleware.dart inside routes/ when behavior should apply only to one route branch.
routes/
admin/
_middleware.dart
_middleware.get.dart
users.get.dart_middleware.dart applies to every matching method in that scope. _middleware.get.dart applies only to GET requests in that scope.
Request-scoped state
Use event.locals when middleware needs to share data with downstream middleware or handlers.
Future<Response> middleware(Event event, Next next) async {
event.locals.set(#startedAt, DateTime.now());
return next();
}This is the preferred place for request-scoped values such as request IDs, timing markers, and authenticated principals.
First-party middleware
Spry exposes first-party middleware helpers from:
import 'package:spry/middleware.dart';Built-in middleware helpers currently include:
Creating your own middleware
Custom middleware should stay small and explicit:
import 'package:spry/spry.dart';
Future<Response> middleware(Event event, Next next) async {
final response = await next();
response.headers.set('x-powered-by', 'spry');
return response;
}Use a first-party helper when the behavior is already covered.
Write your own middleware when the behavior is application-specific.