Reputation: 201
I'm working with Laravel 5.8 and I wanted to set up a Rate Limiter that limits accessing to route by per minute and also IP address.
So I added this to RouteServiceProvider.php
:
protected function configureRateLimiting()
{
RateLimiter::for('limited', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(20)->by($request->ip()),
];
});
}
And then applied it to Route:
Route::get("/", "StaticPages\HomeController@show")->middleware('throttle:limited')->name('home');
So it should be limiting access after 500 attempts or 20 attempts from the same IP address.
But now the problem is it shows 429 Too Many Requests after only ONE attempt!
I don't know why it limits the access after only one attempt.
So what's going wrong here?
How can I properly set the limitation based on IP address to 20 and 500 requests per minute?
Upvotes: 6
Views: 3723
Reputation: 534
I agree with @Bagus Tesa. Laravel 5.8 throttle middleware don't accept parameters except max_rate and per_minutes. Named rate limiting was introduced in Laravel 8 and only available in >= Laravel 8 versions. Either you can implement your own rate limiting middleware or upgrade to Laravel 8 to achieve expected functionality.
Refer: https://laravel.com/docs/5.8/routing#rate-limiting
Upvotes: 1
Reputation: 1
Try go to app\Http\Kernel.php and config if you are using api: 'throttle:[max_rate],[per_minutes]'
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
or try override the function
protected function resolveRequestSignature($request)
{
if ($user = $request->user()) {
return sha1($user->getAuthIdentifier());
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());
}
throw new RuntimeException('Unable to generate the request signature. Route unavailable.');
}
Look closely at the two if statements. If a user is present, the throttle key is based off their user identifier. If a user is not present, the identifier includes $request->ip()
. A request from a different IP address goes in a different limit bucket.
Upvotes: 0
Reputation: 1695
I believe you've read the wrong documentation in your attempt to implement a request rate limiter in Laravel. The "named throttle" is only introduced starting version 8. It is unavailable on version 5.8, please see the laravel documentations for that particular version.
If you declared the throttle in the following way:
Route::get("/", "StaticPages\HomeController@show")->middleware('throttle:20,1')->name('home');
You can see on the returning HTTP Header saying x-ratelimit-remaining
19 after the first request. Hence, the rate limiting working as it supposed to be. However, if you put throttle:limited
it would have no way understanding what does it meant and returns -1 for x-ratelimit-remaining
- and thats why you can open the page once and return HTTP Error 429 for the subsequent requests.
If you still have doubts on my explanation, please put a die()
at the beginning of the configureRateLimiting
as such:
protected function configureRateLimiting()
{
die();
RateLimiter::for('limited', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(20)->by($request->ip()),
];
});
}
If that particular function is actually executed by Laravel, your app should stop working before it can answer any requests. If it isn't, it will just run just fine.
At this point, you only have 2 options on implementing your rate limiter policy: 1) implement your own rate limiter middleware; 2) update your Laravel to at least version 8.
Fyi, on the top right corner of Laravel Documentation page, you can set which version of the documentation you want to read.
Upvotes: 4
Reputation: 161
I think you need to write code [ return response('Custom response...', 429); ] in functions.
RateLimiter::for('limited', function (Request $request) {
return Limit::perMinute(1000)->response(function () {
return response('Custom response...', 429);
});
For more about rate-limiting :
https://laravel.com/docs/8.x/routing#rate-limiting
Upvotes: 1