toni
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 sent

Layer responsibilities

LayerRuns whenCan block?Has response access?
MiddlewareBefore routingYes (by returning error)Response (after next)
GuardsAfter routing, before handlerYes (return false)No
InterceptorsAround handlerYes (skip calling next)Yes (both sides)
PipesDuring param extractionNo (throws instead)No
Error handlersOn any error—Writes the response

Scope levels

Guards, interceptors, pipes, and error handlers can be applied at three scopes, in execution order:

  1. Global — registered on ToniFactory, applies to every route
  2. Controller — annotated on the controller struct with #[use_guards] etc., applies to all routes in that controller
  3. 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

On this page