Middleware Pipeline

A middleware is any callable shaped function (Request $request, callable $next): Response. Call $next($request) to continue the pipeline toward the route's action, or return your own Response to short-circuit it before $next is ever called.

Execution order

Middleware registered first runs outermost — it's the first thing to run on the way in, and the last thing to run on the way out. Middleware registered later sits closer to the route's action:

Route::get('/hello', fn () => Response::text('Hello'))
    ->middleware(function (Request $request, callable $next): Response {
        // runs first, going in
        $response = $next($request);
        // runs last, coming out
        return $response;
    })
    ->middleware(function (Request $request, callable $next): Response {
        // runs second, going in — closest to the action
        $response = $next($request);
        // runs first, coming out
        return $response;
    });

Group middleware (Route::group(['middleware' => ...], ...)) is prepended before any route-level middleware added inside the group, and nested groups accumulate their parent's middleware — see Routing.

Closure or class?

A middleware entry is either an already-callable value (a closure, or an invokable object) used as-is, or a class-string, instantiated with no constructor arguments and invoked directly:

final class AddPoweredByHeader
{
    public function __invoke(Request $request, callable $next): Response
    {
        $response = $next($request);

        return $response->withHeader('X-Powered-By', 'Monad');
    }
}

Route::get('/hello', fn () => Response::text('Hello'))->middleware(AddPoweredByHeader::class);

The zero-constructor-argument rule is why Clarity's built-in security middlewares (Csrf, RateLimiter, Authentication, RBAC) are meant to be registered through a thin subclass in app/Middlewares/ that supplies their real configuration — the skeleton ships one for each. A closure has no such restriction, since it's already callable and never gets instantiated by class name.

Every built-in middleware

  • Csrf — session-token storage, rotation, origin checks.
  • Logger (PSR-3) — request/correlation ID, channel, redaction.
  • Authentication — credential and Google SSO authenticators, remember-me, login throttling.
  • RBAC — role/permission checks, route guards.
  • RateLimiter — required at login, password reset, public API, and LLM call sites.
  • CORS — allowed origins/methods/headers, preflight handling.
  • Jsonify — parses JSON request bodies, feeds Request::json().
  • MetaTag — meta/OG/Twitter/JSON-LD tag generation for a view's <head>.

Next steps