1. Глубже в детали
  2. Ограничение по количеству действий

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

Laravel включает простой в использовании абстрактный класс ограничения количества действий, который, в сочетании с кешем вашего приложения, предоставляет простой способ ограничения любого действия в течение заданного интервала времени.

Примечание Если вас интересует ограничение количества входящих HTTP-запросов, пожалуйста, обратитесь к документации о промежутке времени между запросами.

Конфигурация кеша

Обычно лимитатор количества действий использует кеш вашего приложения по умолчанию, определенный ключом default в конфигурационном файле cache вашего приложения. Однако вы можете указать, какой драйвер кеша должен использовать лимитатор, определив ключ limiter в конфигурационном файле cache вашего приложения:

'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 'modify_10x/rate-limiting.return_text_43';
}

При необходимости вы можете предоставить четвертый аргумент методу attempt, который представляет собой "скорость затухания" или количество секунд до сброса доступных попыток. Например, мы можем изменить приведенный выше пример, чтобы разрешить пять попыток каждые две минуты:

$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 'modify_10x/rate-limiting.return_text_65';
}
 
RateLimiter::hit('send-message:'.$user->id);
 
// Отправить сообщение...

В альтернативе вы можете использовать метод 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 'modify_10x/rate-limiting.return_text_92';
}
 
RateLimiter::hit('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;
}