# Laravel 429 Too Many Requests

Laravel のデフォルトでは1分以内に 60 回以上のリクエストを送信した場合、429Too Many Requests エラーが一定時間発生します。

# エラー解消するための対応

設定ファイル app/Http/kernel.php



 



  protected $middlewareGroups = [
  'api' => [
            'throttle:120,1',
        ],
    ];

throttle に回数と期間(分)を指定すれば、解決します。

throttle function 内容

Illuminate/Routing/Middleware/ThrottleRequests.php


    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  int|string  $maxAttempts
     * @param  float|int  $decayMinutes
     * @param  string  $prefix
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
     */
    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '')
    {
        if (is_string($maxAttempts)
            && func_num_args() === 3
            && ! is_null($limiter = $this->limiter->limiter($maxAttempts))) {
            return $this->handleRequestUsingNamedLimiter($request, $next, $maxAttempts, $limiter);
        }

        return $this->handleRequest(
            $request,
            $next,
            [
                (object) [
                    'key' => $prefix.$this->resolveRequestSignature($request),
                    'maxAttempts' => $this->resolveMaxAttempts($request, $maxAttempts),
                    'decayMinutes' => $decayMinutes,
                    'responseCallback' => null,
                ],
            ]
        );
    }

リクエスト元は、IP アドレスとドメインのハッシュキーから識別しているようで、
デフォルト設定では1分間に 60 回の最大値設定されています。

maxAttempts は最大の試行回数、decayMinutes は一定期間

# API 通信制御

429 エラーを解消するため制限を緩和することは簡単にできますが、フロントエンドで無駄な通信をやめて、lazy 通信や定期通信を選ぶのもあります。
lodash の debounce 使って一定時間止まったら実行させるとか、throttle で一定時間に 1 回ペースを実行させるとかやり方いろいろあります。

# 拡張

API リクエストの制限はデフォルト機能としてありますが、ユーザログインに一定期間内に失敗した回数カウントや同一 IP から一定期間内のアクセス管理にも同じ仕組みで使えそうです。

2023-02-07

同じタグを持つ記事をピックアップしました。