はじめに
Laravelには、アプリケーションの cache と組み合わせて、指定された時間枠内で任意のアクションを制限するための簡単に使用できるレート制限の抽象化が含まれています。
受信HTTPリクエストのレート制限に興味がある場合は、レートリミッターミドルウェアのドキュメント を参照してください。
キャッシュ設定
通常、レートリミッターは、アプリケーションの cache
設定ファイル内の default
キーによって定義されたデフォルトのアプリケーションキャッシュを利用します。ただし、アプリケーションの cache
設定ファイル内に limiter
キーを定義することで、レートリミッターが使用するキャッシュドライバーを指定できます:
'default' => env('CACHE_STORE', 'database'),
'limiter' => 'redis',
基本的な使用法
レートリミッターと対話するために Illuminate\Support\Facades\RateLimiter
ファサードを使用できます。レートリミッターが提供する最も簡単なメソッドは attempt
メソッドで、指定された秒数の間、指定されたコールバックをレート制限します。
attempt
メソッドは、コールバックに残りの試行回数がない場合に false
を返します。それ以外の場合、attempt
メソッドはコールバックの結果または true
を返します。attempt
メソッドが受け入れる最初の引数は、レートリミッターの「キー」であり、レート制限されるアクションを表す任意の文字列を選択できます:
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function() {
// Send message...
}
);
if (! $executed) {
return 'Too many messages sent!';
}
必要に応じて、attempt
メソッドに4番目の引数を提供できます。これは「減衰率」であり、利用可能な試行回数がリセットされるまでの秒数です。たとえば、上記の例を変更して、2分ごとに5回の試行を許可することができます:
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function() {
// Send message...
},
$decayRate = 120,
);
手動での試行回数の増加
レートリミッターと手動で対話したい場合は、さまざまな他のメソッドが利用可能です。たとえば、tooManyAttempts
メソッドを呼び出して、指定されたレートリミッターキーが1分あたりの許可された最大試行回数を超えたかどうかを確認できます:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
return 'Too many attempts!';
}
RateLimiter::increment('send-message:'.$user->id);
// Send message...
また、remaining
メソッドを使用して、指定されたキーの残りの試行回数を取得できます。指定されたキーに残りの再試行がある場合、increment
メソッドを呼び出して、総試行回数を増やすことができます:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
RateLimiter::increment('send-message:'.$user->id);
// Send message...
}
指定されたレートリミッターキーの値を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 'You may try again in '.$seconds.' seconds.';
}
RateLimiter::increment('send-message:'.$user->id);
// Send message...
試行回数のクリア
指定されたレートリミッターキーの試行回数をリセットするには、clear
メソッドを使用できます。たとえば、指定されたメッセージが受信者によって読み取られたときに試行回数をリセットできます:
use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;
/**
* Mark the message as read.
*/
public function read(Message $message): Message
{
$message->markAsRead();
RateLimiter::clear('send-message:'.$message->user_id);
return $message;
}