Laravel 开箱即用地提供了两个可用于速率限制(节流)的中间件:
\Illuminate\Routing\Middleware\ThrottleRequests::class
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
正如文档所述,如果您使用 Redis 作为缓存驱动程序,您可以更改
Kernel.php
中的映射,如下所示:
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
// ...
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
// ...
];
问题是上述内容不是动态的,依赖于环境。例如,在我的
staging
和 production
环境中,我使用 Redis,但在我的 local
和 development
环境中,我不使用 Redis。
有一个明显的脏修复,类似于这个(Kernel.php
):
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
// ...
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class
// ...
];
/**
* Create a new HTTP kernel instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function __construct(Application $app, Router $router)
{
if ($app->environment('production')) {
$this->middlewareAliases['throttle'] = \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;
}
parent::__construct($app, $router);
}
是否有一种“标准”方法可以实现此目的,而无需重写 Kernel
构造函数?本质上,我希望我的应用程序根据环境是否设置为
production
(或者默认缓存存储设置为
redis
)来动态选择相关中间件。更新
ThrottleRequests
类,以便动态调用相关类。
throttle
中动态设置
RouteServiceProvider
中间件,如下所示:
class RouteServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
$this->registerThrottleMiddleware();
}
/**
* Register the middleware used for throttling requests.
*
* @return void
*/
private function registerThrottleMiddleware(): void
{
$router = app()->make('router');
$middleware = config('cache.default') !== 'redis'
? \Illuminate\Routing\Middleware\ThrottleRequests::class
: \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;
$router->aliasMiddleware('throttle', $middleware);
}
}
throttleWithRedis()
上使用
bootstrap/app.php
助手。如下图:
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__ . '/../routes/web.php',
api: __DIR__ . '/../routes/api.php',
commands: __DIR__ . '/../routes/console.php',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->throttleWithRedis();
})