#Введение
Laravel включает простую в использовании абстракцию ограничения частоты запросов, которая в сочетании с кэшем вашего приложения предоставляет удобный способ ограничить любое действие в течение заданного временного интервала.
Если вы хотите ограничить входящие HTTP-запросы, пожалуйста, ознакомьтесь с документацией по middleware для ограничения частоты запросов.
#Настройка кэша
Обычно rate limiter использует кэш приложения по умолчанию, определённый ключом default в конфигурационном файле cache вашего приложения. Однако вы можете указать, какой драйвер кэша должен использовать rate limiter, задав ключ limiter в конфигурации cache:
'default' => 'memcached',
'limiter' => 'redis',
#Основное использование
Фасад Illuminate\Support\Facades\RateLimiter можно использовать для взаимодействия с ограничителем частоты. Самый простой метод — attempt, который ограничивает выполнение переданного callback на заданное количество секунд.
Метод attempt возвращает false, когда у колбэка не осталось доступных попыток; в противном случае метод attempt вернёт результат колбэка или true. Первым аргументом, принимаемым методом attempt, является "ключ" ограничителя частоты запросов — это может быть любая строка, обозначающая действие, к которому применяется ограничение:
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function() {
// Отправить сообщение...
}
);
if (! $executed) {
return 'Слишком много отправленных сообщений!';
}
При необходимости вы можете передать четвёртый аргумент в метод attempt — "время сброса" (decay rate), то есть количество секунд до сброса доступных попыток. Например, изменим пример выше, чтобы разрешить пять попыток каждые две минуты:
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function() {
// Отправить сообщение...
},
$decayRate = 120,
);
#Ручное увеличение количества попыток
Если вы хотите вручную управлять ограничителем частоты, доступны различные методы. Например, метод tooManyAttempts позволяет проверить, превысил ли заданный ключ максимальное количество попыток в минуту:
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);
// Отправить сообщение...
}
Если нужно увеличить значение для ключа ограничителя частоты более чем на единицу, передайте желаемое количество в метод 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;
}