How to use Laravel Rate Limiter

Pavel Buchnev
2 min readApr 2, 2019

--

Всем привет.

Недавно я разрабатывал сервис, в котором клиент должен был сам вводить номер телефона, после чего ему должно было отправиться СМС, причем не было ограничения на вводимые номера, он мог ввести один номер телефона, нажать кнопку отправить, далее указать новый номер телефона и снова отправить, и каждый раз когда клиент указывает новый номер нужно было отправить смс, а т.к. смс стоит денег, то ограничить отправку не более 5 смс в 10 минут. Получается запросов может быть сколько угодно, но считаем только те, при которых произошла отправка смс. Данную задачу можно решить при помощи middleware throttle, но в этом случае мы ограничим кол-во запросов, помимо номера передаются другие данные, поэтому нужно ограничить только по кол-ву смс.

В Laravel нигде особо нет описания класса \Illuminate\Cache\RateLimiter, но именно он помогает throttle управлять лимитами. По сути магии то никакой нет. Когда пользователь проходит через этот middleware, то происходит следующее:

  1. Для пользователя создается уникальный ключ.
if ($user = $request->user()) {
$key = sha1($user->getAuthIdentifier());
}

if ($route = $request->route()) {
$key = sha1($route->getDomain().'|'.$request->ip());
}

2. В Rate Limiter происходит проверка для этого ключа, а не привышено ли кол-во запросов для него.

$maxAttempts = 5;
if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
throw new ThrottleRequestsException(...);
}

Если превышено, то выводим пользователю сообщение о превышении лимита, если нет, то увеличиваем счетчик обращений

$decayMinutes = 1; // Промежуток времени за который можно совершить n обращений (например 60 обращений в минуту)
$this->limiter->hit($key, $decayMinutes);

Это все. Получается для решения задачи нам нужно нечто подобное. (Я специально сделал внешний вид класса как можно проще, т.к. все действия я описал выше.)

Я решил ограничиться одним методом throttle, при вызове которого в него передавается только ключ и callback, которы выполняется только в том, случае если, лимит не превышен.

И теперь осталось только использовать этот класс в нужном месте.

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

Буду рад, если кому нибудь пригодится!

--

--

Pavel Buchnev
Pavel Buchnev

Written by Pavel Buchnev

Senior PHP Developer | Contributor to Spiral Framework 🚀 | Enthusiast of RoadRunner & long-running applications | Creator of Buggregator

Responses (1)