Docs LATEST

HTTP Configuration

Middleware and rate limiting.

Configuration

config/http.php controls middleware aliases, global middleware, and rate limiting.


Middleware aliases #

Built-in middleware aliases:

Alias Class
errors VelvetCMS\Http\Middleware\ErrorHandlingMiddleware
throttle VelvetCMS\Http\Middleware\ThrottleRequests
csrf VelvetCMS\Http\Middleware\VerifyCsrfToken
session VelvetCMS\Http\Middleware\StartSessionMiddleware

Global middleware #

The default global stack applies to every request:

'global' => [
    'errors',
    'session',
    'throttle',
],

Override in user/config/http.php.


Rate limiting #

Rate limiting uses named limiters with configurable attempts, decay windows, and key strategies.

Configuration #

'rate_limit' => [
    'enabled' => true,
    'default' => 'standard',

    'limiters' => [
        'standard' => ['attempts' => 60, 'decay' => 60, 'by' => 'ip'],
        'api' => ['attempts' => 120, 'decay' => 60, 'by' => 'ip'],
        'auth' => ['attempts' => 5, 'decay' => 60, 'by' => 'ip'],
        'strict' => ['attempts' => 10, 'decay' => 60, 'by' => 'ip'],
    ],

    'whitelist' => ['127.0.0.1', '::1'],
],

Config keys #

Key Default Description
enabled true Enable/disable rate limiting globally
default 'standard' Default limiter name when none specified
limiters See above Named limiter definitions
whitelist ['127.0.0.1', '::1'] IPs that bypass rate limiting

Limiter options #

Option Description
attempts Maximum requests per window
decay Window length in seconds
by Key strategy: ip, ip_route, or custom

Using named limiters #

Apply a named limiter to routes:

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

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

Inline limits #

You can also specify limits inline:

->middleware('throttle:10,1')  // 10 attempts per 1 minute

Programmatic 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-api', function ($request) {
    $userId = $request->session()->get('user_id');
    // Your logic to check user tier
    return $userId && isPremiumUser($userId)
        ? Limit::perMinute(1000)
        : Limit::perMinute(60);
});

// Unlimited for certain conditions
$rateLimiter->for('internal', fn() => Limit::none());

Limit value object #

The Limit class provides fluent limit definitions:

Limit::perMinute(60);       // 60 requests per minute
Limit::perHour(1000);       // 1000 requests per hour
Limit::perDay(10000);       // 10000 requests per day
Limit::perSeconds(30, 10);  // 10 requests per 30 seconds
Limit::none();              // Unlimited (bypass)

Customize the key strategy:

Limit::perMinute(60)->by('ip');        // Default: by IP address
Limit::perMinute(60)->by('ip_route');  // By IP + route combination
Limit::perMinute(60)->withKey('custom-key');  // Custom key

Response headers #

Rate-limited responses include these headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1706123456

When the limit is exceeded, a 429 Too Many Requests response is returned with a Retry-After header.