レート制限
イントロダクション
Laravelは、アプリケーションのキャッシュと連携し、指定した時間内のアクションを簡単に制限できる、シンプルなレート制限の抽象化を用意しています。
受信HTTPリクエストのレート制限に興味がある場合は、レート制限ミドルウェアのドキュメントを参照してください。
キャッシュ設定
通常、レートリミッタは、アプリケーションのcache設定ファイル内のdefaultキーで定義されているデフォルトのアプリケーションキャッシュを利用します。ただし、アプリケーションのcache設定ファイル内にlimiterキーを定義することで、レートリミッタが使用するキャッシュドライバを指定できます。
1'default' => env('CACHE_STORE', 'database'),2 3'limiter' => 'redis',
基本的な使い方
Illuminate\Support\Facades\RateLimiterファサードは、レートリミッタを操作するために使用します。レートリミッタが提供する最も単純なメソッドはattemptメソッドで、これは特定のコールバックを指定した秒数だけレート制限します。
attemptメソッドは、コールバックの試行回数が残っていない場合はfalseを返します。それ以外の場合、attemptメソッドはコールバックの結果またはtrueを返します。attemptメソッドが受け取る最初の引数はレートリミッタの「キー」で、レート制限されるアクションを表す任意の文字列を指定できます。
1use Illuminate\Support\Facades\RateLimiter; 2 3$executed = RateLimiter::attempt( 4 'send-message:'.$user->id, 5 $perMinute = 5, 6 function() { 7 // Send message... 8 } 9);10 11if (! $executed) {12 return 'Too many messages sent!';13}
必要であれば、attemptメソッドの第4引数として「減衰率」、つまり利用可能な試行回数がリセットされるまでの秒数を指定できます。たとえば、上記の例を2分ごとに5回の試行を許可するように変更できます。
1$executed = RateLimiter::attempt(2 'send-message:'.$user->id,3 $perTwoMinutes = 5,4 function() {5 // Send message...6 },7 $decayRate = 120,8);
手動による試行回数の加算
レートリミッタを手動で操作したい場合は、他のさまざまなメソッドが利用できます。たとえば、tooManyAttemptsメソッドを呼び出して、特定のレートリミッタキーが1分あたりの最大許容試行回数を超えたかどうかを判断できます。
1use Illuminate\Support\Facades\RateLimiter;2 3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {4 return 'Too many attempts!';5}6 7RateLimiter::increment('send-message:'.$user->id);8 9// Send message...
あるいは、remainingメソッドを使用して、特定のキーに残っている試行回数を取得できます。特定のキーに再試行が残っている場合は、incrementメソッドを呼び出して総試行回数をインクリメントできます。
1use Illuminate\Support\Facades\RateLimiter;2 3if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {4 RateLimiter::increment('send-message:'.$user->id);5 6 // Send message...7}
特定のレートリミッタキーの値を1より多くインクリメントしたい場合は、incrementメソッドに希望する量を指定できます。
1RateLimiter::increment('send-message:'.$user->id, amount: 5);
リミッタの利用可能性の判定
キーに試行回数が残っていない場合、availableInメソッドは、次の試行が可能になるまでの残り秒数を返します。
1use Illuminate\Support\Facades\RateLimiter; 2 3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) { 4 $seconds = RateLimiter::availableIn('send-message:'.$user->id); 5 6 return 'You may try again in '.$seconds.' seconds.'; 7} 8 9RateLimiter::increment('send-message:'.$user->id);10 11// Send message...
試行回数のクリア
clearメソッドを使用して、特定のレートリミッタキーの試行回数をリセットできます。たとえば、受信者が特定のメッセージを読んだときに試行回数をリセットできます。
1use App\Models\Message; 2use Illuminate\Support\Facades\RateLimiter; 3 4/** 5 * Mark the message as read. 6 */ 7public function read(Message $message): Message 8{ 9 $message->markAsRead();10 11 RateLimiter::clear('send-message:'.$message->user_id);12 13 return $message;14}