i created a page visit function that works with laravel throttle. each ip/user can increase visit counter every 60 minutes.
i have a problem that can’t apply throttle on different ids and throttle works on route only 1 time per 60 minutes and does’nt care about ids:
(/home/visit/3 , /home/visit/4 ,…..): 1 time every 60 mins
route.php:
Route::post('/home/visit/{id}',[HomeController::class,'counter_visit'])->middleware('throttle:visit');
RouteServiceProvider.php
RateLimiter::for('visit', function (Request $request) {
return $request->user()
? Limit::perHour(1)->by($request->user()->id)
: Limit::perHour(1)->by($request->ip());
});
how can i apply throttle for each id like below?
/home/visit/3 : 1 time every 60 mins
/home/visit/4 : 1 time every 60 mins
thanks for your helps
2
Answers
i found the easiest way(maybe). just create a custom middleware extending ThrottleRequests.
HttpmiddlewareThrottleById.php.
this function creates uique signature for each url if id parameter of route is different then just add this middleware to kernel.php same as part 3 & 4 in https://stackoverflow.com/a/75869783/9241751
thanks to Balaji Kandasamy
Currently, you are using Laravel’s built-in throttle middleware, which limits the number of requests for a given route per user or IP address, regardless of the ID parameter. To achieve throttling based on ID parameters, you need to define your own custom middleware.
Here’s an example of how you can create a custom middleware that throttles requests based on ID:
php artisan make:middleware ThrottleById
Open the newly created ThrottleById middleware class and modify the handle() method to include the following code:
use IlluminateCacheRateLimiter;
use SymfonyComponentHttpFoundationResponse;
use IlluminateHttpExceptionsThrottleRequestsException;
public function handle($request, Closure $next, $maxAttempts = 1, $decayMinutes = 60)
{
$limiter = app(RateLimiter::class)->for(‘visit_’.$request->route(‘id’), $maxAttempts, $decayMinutes);
if ($limiter->tooManyAttempts($request)) {
$retryAfter = $limiter->availableIn($request);
throw new ThrottleRequestsException(null, $retryAfter, [
‘Retry-After’ => $retryAfter,
‘X-RateLimit-Limit’ => $maxAttempts,
‘X-RateLimit-Remaining’ => 0,
]);
}
}
The above code is an implementation of Laravel’s built-in throttle middleware, but modified to use the ID parameter of the request to create a unique cache key for each ID.
Next, register the middleware in the $routeMiddleware array in the AppHttpKernel class:
protected $routeMiddleware = [ // ... 'throttle_by_id' => AppHttpMiddlewareThrottleById::class, ];
Finally, apply the new middleware to your route definition like this:
Route::post('/home/visit/{id}', [HomeController::class, 'counter_visit'])->middleware('throttle_by_id');