Laravel: There is a RateLimiter and you didn’t know

This class is not registered in the Service Container, but you can instance it using the app helper anywhere in your code.

$limiter = app(RateLimiter::class);If in your code you plan to use the RateLimiter constantly you can conveniently type-hint the class, like in Controller handlers.

/** * Do something tied to rate limiting * * @param IlluminateCacheRateLimiter $limiter * @return IlluminateHttpResponse * @throws IlluminateValidationValidationException */public function notTooManyTimes(RateLimiter $limiter){ if ($limiter->tooManyAttempts('my_action')) { // .

do something } // .

}It receives the default Cache Store of your application, which in fresh installations is the file one.

Since you have control in the instancing, you can swap your Cache for another:$limiter = app(RateLimiter::class, [ 'cache' => Cache::store('memcache') ]);In the case where you want to use a custom store everywhere, you can tell the Service Container to use another Cache when the RateLimiter is resolved anywhere in your AppServiceProvider:/** * Bootstrap any application services.

* * @return void */public function boot(){ // .

$this->app ->when(IlluminateCacheRateLimiter::class) ->needs(IlluminateContractsCacheRepository::class) ->give(function ($app) { return $app->make('cache')->store('memcached'); });This will affect all instances of the RateLimiter.

For more granular control, you could extend this class and register it in the Service Container with your own Cache Store to pick, or even use tagging.

The sky's the limit, boys and girls!Basic usageThe basic flow of rate-limiting something is this:You check if the action has attempts left with tooManyAttempts().

If not, do something, like throwing your favorite Exception like Validation Exception, which is something the ThrottlesLogins trait does.

You use hit() each time you want subtract 1 to the attempts left, with the name to identify what rate limiter and the decay seconds of it.

Optionally, reset the counter using resetAttempts(), or additionally reset the timer using clear().

There are other methods like:attempts(): shows you how many attempts the user has been done.

retriesLeft(): The number of retries left.

available(): How much time must pass to retry.

These are useful to tell the user it has tried X times, has X retries left, or to tell the user he can proceed after X time.

Can we stop reckless Requests?The RateLimiter is very basic.

Most of the time you can stop the user using the throttle middleware, leaving our controller logic clean.

But sometimes, we need to use the Request to effectively throttle an action, which you can’t do with the throttle middleware alone.

For example, we can use this to handle how many times a user can send a Podcast Analytics to a reportable email.

Since this calculation is costly for the application, we can add a rate limiter to avoid queueing the SendPodcastAnalyticsJob in the next hour or so.

I know this example as a better solution, but is just here to prove a point:In addition to this, we could stop the propagation of the form submission using JavaScript, just to be sure the user don’t click more than one time by accident before seeing the result.

You are free to use the RateLimiter in whatever you want, but it’s often more useful in controllers, before the real logic is executed, like before firing an Event or pushing a Job.

No need to clog up your application with packages or hack into your application, or create your own Rate Limiter from the ground.

RateLimiter is just there, ready to be used.


. More details

Leave a Reply