В последнее время я всё чаще и чаще работаю над созданием API при разработке на Laravel. Я использую свой класс для ручного ограничения скорости запросов, но мне всегда казалось, что для этого есть более простое решение. И не удивительно, что когда Тэйлор собрался написать посредник для ограничения скорости запросов, то у него это вышло проще и лучше, чем у меня. Это одна из статей о новых функциях Laravel 5.2. Скоро будут ещё, не пропустите. {{Cut}} 1. ((https://laravel.ru/posts/354 Проверка массива формы в Laravel 5.2)) 2. ((https://laravel.ru/posts/372 Неявная привязка модели маршрута в Laravel 5.2)) 3. ((https://laravel.ru/posts/379 Ограничение скорости запросов API в Laravel 5.2)) 4. ((https://laravel.ru/posts/380 Заготовка авторизации в Laravel 5.2)) 5. ((https://laravel.ru/posts/381 Множественные драйверы защиты авторизации (включая API) в Laravel 5.2)) == Краткое введение в ограничение скорости запросов == Если вы ещё не знакомы с ним, то ограничение скорости - это часто используемый в API инструмент, который //ограничивает скорость// запросов для каждого отдельного запрашивающего. Это означает, например, если какой-нибудь бот обращается к довольно затратному API-маршруту тысячу раз в минуту, ваше приложение не упадёт, потому что после n-й попытки он получит от сервера ответ %%(t)429: Too Many Attempts%% (слишком много попыток). Обычно хорошо написанное приложение, использующее ограничение скорости, в отличие от других приложений будет также возвращать три заголовка: %%(t)X-RateLimit-Limit%%, %%(t)X-RateLimit-Remaining%% и %%(t)Retry-After%% (если вы достигните предела, то получите только %%(t)Retry-After%%). %%(t)X-RateLimit-Limit%% - это максимальное число запросов для приложения, разрешённое в данном интервале времени. %%(t)X-RateLimit-Remaining%% - это сколько запросов у вас осталось в данном интервале времени. А %%(t)Retry-After%% - это сколько секунд надо ждать до следующей попытки. (%%(t)Retry-After%% может быть не количеством секунд, а датой). .(alert) Каждый API выбирает свой интервал времени для ограничения. У GitHub он равен часу, у Twitter - 15 минут. У данного посредника Laravel - 1 минута. == Как использовать посредник для ограничения скорости запросов Laravel == Рассмотрим новую возможность Laravel 5.2. Появился новый посредник %%(t)throttle%%. Посмотрим на нашу группу API: %% Route::group(['prefix' => 'api'], function () { Route::get('people', function () { return Person::all(); }); }); %% Применим к ней %%(t)throttle%%. По умолчанию его предел - 60 попыток в минуту, ограничение длится в течение той минуты, когда достигнут предел. %% Route::group(['prefix' => 'api', 'middleware' => 'throttle'], function () { Route::get('people', function () { return Person::all(); }); }); %% Теперь при запросе к этому маршруту %%(t)api/people%% вы увидите такие строчки в заголовках ответов: %%(t) HTTP/1.1 200 OK ... other headers here ... X-RateLimit-Limit: 60 X-RateLimit-Remaining: 59 %% Запомните, этот ответ значит: а) этот запрос успешный (статус 200) б) вы можете обращаться к этому маршруту со скоростью 60 раз в минуту в) у вас осталось 59 запросов в этой минуте Какой ответ мы получим, если достигнем предела: %%(t) HTTP/1.1 429 Too Many Requests ... other headers here ... Retry-After: 60 X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 %% И содержимым ответа будет строка: %%(t)Too Many Attempts.%% (слишком много попыток). А если попробовать через 30 секунд? %% HTTP/1.1 429 Too Many Requests ... other headers here ... Retry-After: 30 X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 %% Тот же ответ, только таймер %%(t)Retry-After%%, означающий сколько надо подождать, уже на отметке 30. == Настройка посредника %%(t)throttle%% == Давайте немного настроим. Сделаем ограничение на 5 попыток в минуту. %% Route::group(['prefix' => 'api', 'middleware' => 'throttle:5'], function () { Route::get('people', function () { return Person::all(); }); }); %% А теперь сделаем так, что если кто-то достигнет предела, то ему надо будет ждать 10 минут. %% Route::group(['prefix' => 'api', 'middleware' => 'throttle:5,10'], function () { Route::get('people', function () { return Person::all(); }); }); %% Вот и всё! Код вы можете найти здесь: ((https://github.com/illuminate/routing/blob/master/Middleware/ThrottleRequests.php ThrottlesRequests.php)).