イントロダクション
Laravelには、簡単に使用できるレート制限の抽象化機能があり、アプリケーションのcacheと連携して、指定した時間帯のアクションを制限する簡単な方法を提供します。
Tip!! 受信HTTPリクエストのレートを制限したい場合は、レート制限ミドルウェアのドキュメントを参照してください。
キャッシュ設定
通常、レート制限では、アプリケーションのcache
設定ファイルのdefault
キーで定義されているデフォルトのアプリケーションキャッシュを使用します。しかし、アプリケーションのcache
設定ファイル内でlimiter
キーを定義すれば、レート制限で使用するキャッシュドライバを指定できます。
'default' => 'memcached',
'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() {
// メッセージ送信…
}
);
if (! $executed) {
return 'Too many messages sent!';
}
試行回数の手動増加
レート制限を手動で操作する場合は、他にもさまざまな方法があります。たとえば、tooManyAttempts
メソッドを呼び出して、指定したレート制限キーが1分間に許可した最大試行回数を超えたかを判断できます。
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
return 'Too many attempts!';
}
他にも、remaining
メソッドを使って、指定キーの残りの試行回数を取得することも可能です。指定キーに再試行回数が残っている場合は、hit
メソッドを呼び出して総試行回数を増やせます。
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
RateLimiter::hit('send-message:'.$user->id);
// メッセージ送信…
}
使用可能時間の判断
キーの試行回数がなくなると、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.';
}
試行のクリア
clear
メソッドを使って、任意のレート制限キーの試行回数をリセットできます。例えば、指定メッセージが受信者によって読まれたときに試行回数をリセットできます。
use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;
/**
* メッセージを既読としてマーク
*
* @param \App\Models\Message $message
* @return \App\Models\Message
*/
public function read(Message $message)
{
$message->markAsRead();
RateLimiter::clear('send-message:'.$message->user_id);
return $message;
}