Docs LATEST

Middleware

Global and per-route middleware.

HTTP & Routing

Middleware can be global or attached per route.

$router->registerMiddleware('auth', AuthMiddleware::class);
$router->pushMiddleware('errors');
$router->get('/admin', [AdminController::class, 'index'])
    ->middleware('auth');

Built-in middleware #

  • ErrorHandlingMiddleware (aliased as errors by default)
  • StartSessionMiddleware
  • VerifyCsrfToken
  • ThrottleRequests

Aliases and global stack #

Aliases are defined in config/http.php under middleware.aliases. Global middleware lives in middleware.global and is applied to every route.

If no global middleware is configured, errors is added automatically.

Rate limiting middleware #

The throttle middleware provides request rate limiting with named limiters.

Basic usage #

// Use default limiter ('standard': 60 req/min)
$router->get('/api/posts', [ApiController::class, 'index'])
    ->middleware('throttle');

// Use a named limiter
$router->post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:auth');  // 5 req/min

$router->post('/api/data', [ApiController::class, 'store'])
    ->middleware('throttle:api');   // 120 req/min

Built-in limiters #

Name Attempts Window Use case
standard 60 1 min Default for all routes
api 120 1 min API endpoints
auth 5 1 min Login/password reset
strict 10 1 min Sensitive operations

Inline limits #

Specify attempts and minutes directly:

->middleware('throttle:30,1')   // 30 requests per 1 minute
->middleware('throttle:100,5')  // 100 requests per 5 minutes

Registering custom limiters #

Modules can register dynamic limiters via the RateLimiter service:

use VelvetCMS\Http\RateLimiting\Limit;
use VelvetCMS\Http\RateLimiting\RateLimiter;

$rateLimiter = app(RateLimiter::class);

// Static limit
$rateLimiter->for('uploads', Limit::perMinute(10));

// Dynamic limit based on session
$rateLimiter->for('premium', function ($request) {
    $userId = $request->session()->get('user_id');
    // Your logic to check if user is premium
    return $userId && isPremiumUser($userId)
        ? Limit::perHour(1000)
        : Limit::perHour(100);
});

See HTTP Configuration for full configuration options.