#はじめに
Laravel は使いやすいレート制限の抽象化を提供しており、アプリケーションのキャッシュと組み合わせて、指定した時間内に任意のアクションを制限できます。
受信する HTTP リクエストのレート制限に関心がある場合は、rate limiter middleware のドキュメントをご覧ください。
#キャッシュ設定
通常、レートリミッターはアプリケーションの cache 設定ファイル内の default キーで定義されたデフォルトのキャッシュを使用します。ただし、cache 設定ファイル内に limiter キーを定義することで、レートリミッターが使用するキャッシュドライバーを指定できます:
'default' => 'memcached',
'limiter' => 'redis',
#基本的な使い方
Illuminate\Support\Facades\RateLimiter ファサードを使ってレートリミッターとやり取りできます。最も簡単なメソッドは attempt で、指定した秒数の間、指定したコールバックの実行を制限します。
attempt メソッドは、コールバックに利用可能な残りの試行回数がない場合に false を返します。そうでなければ、コールバックの戻り値または true を返します。attempt メソッドが受け取る最初の引数はレートリミッターの「キー」で、レート制限の対象となるアクションを表す任意の文字列を指定できます:
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function() {
// メッセージを送信...
}
);
if (! $executed) {
return 'メッセージの送信回数が多すぎます!';
}
必要に応じて、attempt メソッドの4番目の引数に「減衰時間」(利用可能な試行回数がリセットされるまでの秒数)を指定できます。例えば、以下のように2分ごとに5回の試行を許可できます:
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function() {
// メッセージを送信...
},
$decayRate = 120,
);
#手動で試行回数を増やす
レートリミッターを手動で操作したい場合は、他にもさまざまなメソッドがあります。例えば、tooManyAttempts メソッドを使うと、指定したレートリミッターキーが1分あたりの最大試行回数を超えているかどうかを判定できます:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
return '試行回数が多すぎます!';
}
RateLimiter::increment('send-message:'.$user->id);
// メッセージを送信...
また、remaining メソッドを使って指定したキーの残り試行回数を取得できます。残りがある場合は increment メソッドで試行回数を増やせます:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
RateLimiter::increment('send-message:'.$user->id);
// メッセージを送信...
}
指定したレートリミッターキーの値を1以上増やしたい場合は、increment メソッドに増やしたい数を指定できます:
RateLimiter::increment('send-message:'.$user->id, amount: 5);
#リミッターの利用可能時間を確認する
キーの試行回数が残っていない場合、availableIn メソッドは次に試行可能になるまでの秒数を返します:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
$seconds = RateLimiter::availableIn('send-message:'.$user->id);
return $seconds.'秒後に再試行できます。';
}
RateLimiter::increment('send-message:'.$user->id);
// メッセージを送信...
#試行回数のリセット
clear メソッドを使うと、指定したレートリミッターキーの試行回数をリセットできます。例えば、メッセージが受信者に読まれたときに試行回数をリセットする場合:
use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;
/**
* メッセージを既読にする。
*/
public function read(Message $message): Message
{
$message->markAsRead();
RateLimiter::clear('send-message:'.$message->user_id);
return $message;
}