Pratique Laravel consistant à utiliser Redis pour la limitation de courant uniquement dans un environnement de production
P粉541565322
P粉541565322 2024-01-10 17:54:47
0
1
426

Contexte

Par défaut, Laravel fournit deux middlewares pour la limitation du débit (throttling) :

\Illuminate\Routing\Middleware\ThrottleRequests::class
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class

Comme l'indique la documentation, si vous utilisez Redis comme pilote de cache, vous pouvez modifier le mappage dans Kernel.php comme ceci :

/**
 * 应用程序的中间件别名。
 *
 * 别名可用于将中间件方便地分配给路由和组,而不是使用类名。
 *
 * @var array<string, class-string|string>
 */
protected $middlewareAliases = [
    // ...
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
    // ...
];

Question

Le problème est que ce qui précède n'est pas dynamique mais dépendant de l'environnement. Par exemple, dans mon stagingproduction环境中,我使用Redis,但在我的localdevelopmentenvironnement, je n'utilise pas Redis.

Solutions possibles

Il existe une solution sale évidente, quelque chose comme ceci (Kernel.php) :

/**
 * 应用程序的中间件别名。
 *
 * 别名可用于将中间件方便地分配给路由和组,而不是使用类名。
 *
 * @var array<string, class-string|string>
 */
protected $middlewareAliases = [
    // ...
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class
    // ...
];

/**
 * 创建一个新的HTTP内核实例。
 *
 * @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);
}

Existe-t-il un moyen "standard" de sélectionner dynamiquement un middleware pertinent sans écraser Kernel构造函数的情况下实现这一点?基本上,我希望我的应用程序可以根据环境是否设置为production(或者默认缓存存储设置为redis).

Mise à jour

La solution ci-dessus ne fonctionne pas car l'accès au noyau est effectué avant le démarrage de l'application, l'environnement n'est donc pas disponible pour le moment. Une autre solution que j'étudie maintenant consiste à étendre la classe de base ThrottleRequests afin que les classes pertinentes puissent être appelées dynamiquement.

P粉541565322
P粉541565322

répondre à tous(1)
P粉043432210

Après de nombreuses recherches et tests, je suis arrivé à la conclusion que RouteServiceProvider中动态设置throttlemiddleware est la meilleure solution, le code est le suivant :

class RouteServiceProvider extends ServiceProvider
{
    /**
     * 启动任何应用程序服务。
     *
     * @return void
     */
    public function boot(): void
    {
        $this->registerThrottleMiddleware();
    }

    /**
     * 注册用于限制请求的中间件。
     *
     * @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);
    }
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal