HTTP Configuration
Middleware and rate limiting.
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.