Reputation: 1100
I'm writing a lot of API to get and store data.
I like the default throttle
option:
protected $middlewareGroups = [
'api' => [
'throttle:60,1',
'bindings',
],
];
to limit the request to 60 per minute; but for some route (es: POST
), I'd like to increase this value.
I tried to set 'throttle:500,1'
on route Middleware like below:
Route::group(function () {
Route::get('semaphore/1', ['uses' => 'App\Api\V1\DBs\SemaphoreController@index']);
Route::post('semaphore/1', ['uses' => 'App\Api\V1\DBs\SemaphoreController@store', 'middleware' => 'WriteToDatabaseMiddleware', 'throttle:500,1']);
});
but it does not work.
Any idea?
Thank you.
UPDATE:
I noticed that the 'throttle:500,1'
used in the api.php
route will be set AFTER the default 'throttle:60,1'
specified into Kernel.php
file; then, It doesn't work.
Logging the process execution, the first call is:
Illuminate\Routing\Middleware\ThrottleRequests -> handle
from Kernel.php
has maxAttempts=60
.
Then, the second call is:
Illuminate\Routing\Middleware\ThrottleRequests -> handle
from api.php
has maxAttempts=500
.
In others words, the throttle:500,1
in the api.php
file do not override the throttle:60,1
in the Kernel.php
file.
Upvotes: 31
Views: 57875
Reputation: 48758
None of the current answers explain Laravel 5.x behaviour. In that version every instance of "throttle" uses the same bucket. So if you place a throttle command in two separate locations it affects every instance.
Consider:
// User can email 5 times an hour
Route::post('/email', 'Ctrl@email')->middleware('throttle:5,60');
// User can search 100 times an hour
Route::get('/search', 'Ctrl@search')->middleware('throttle:100,60);
If a user searches 5 times in a 5 minute period, they will not able to email in the next hour.
In Laravel 5.x there is no way around this. In Laravel 6 onwards they added the ability to name throttles, giving them separate buckets.
Upvotes: 4
Reputation: 712
In laravel 6 you can use prefix for prevent with global throttle.
use 'throttle:5,1,prefix'
Route::group(['prefix' => 'contact-us', 'middleware' => 'throttle:5,1,contact-form',], function () {
Route::post('/', 'ContactUsController@store');
});
Allow multiple throttles by naming
Upvotes: 4
Reputation: 7289
According to this GitHub issue, the throttle middleware should not be used "twice" (like you want to do that). There are only two ways how to deal with your current problem "correctly":
or
You set the middleware key wrong! When declaring multiple middleware to use, create a new array for them
['middleware' => ['WriteToDatabaseMiddleware','throttle:500,1']]
EDIT: Because of the middleware order, you should set your kernel throttle to the highest value you want to use, and all other routes that should have a lower throttle value to the corresponding ones.
Upvotes: 21