Request Lifecycle
Request Lifecycle
How a request moves through middleware, guards, interceptors, the handler, and back.
Every request travels through a predictable sequence of processing layers before the route handler runs, and through a symmetric sequence on the way back out.
The sequence
Incoming request
│
â–¼
Middleware (runs before routing)
│
â–¼
Guards (authorization check — can this request proceed?)
│
â–¼
Interceptors (before — can transform request, short-circuit)
│
â–¼
Pipes (validate and transform extracted data)
│
â–¼
Route handler (your fn)
│
â–¼
Interceptors (after — can transform response)
│
â–¼
Exception filters / Error handlers (if handler or chain threw)
│
â–¼
Response sentLayer responsibilities
| Layer | Runs when | Can block? | Has response access? |
|---|---|---|---|
| Middleware | Before routing | Yes (by returning error) | Response (after next) |
| Guards | After routing, before handler | Yes (return false) | No |
| Interceptors | Around handler | Yes (skip calling next) | Yes (both sides) |
| Pipes | During param extraction | No (throws instead) | No |
| Error handlers | On any error | — | Writes the response |
Scope levels
Guards, interceptors, pipes, and error handlers can be applied at three scopes, in execution order:
- Global — registered on
ToniFactory, applies to every route - Controller — annotated on the controller struct with
#[use_guards]etc., applies to all routes in that controller - Method — annotated on a specific route handler, applies only to that route
All levels run, in that order. Method-level runs in addition to controller-level and global, not instead.
Sections in this chapter
- Middleware — request processing before routing
- Guards — authorization and access control
- Interceptors — cross-cutting logic wrapping handlers
- Pipes — data transformation and validation
- Exception Filters — structured error handling