Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel RateLimiter

I'm fairly new to Laravel and am currently using an API that has a limit of 25 requests per minute. I have a controller method sendRequest() which is used by all methods to send requests to the API so I was thinking this is the place to put a rate limiter that checks if the current request can be added to the queue if the limit is not yet reached.

I was thinking something like this:

protected function sendRequest(){
    if ($this->allowRequest()) {
        //proceed to api call
    }
}

protected function allowRequest() {
    $allow = false;
    //probably a do-while loop to check if the limit has been reached within the timeframe?
}

I've found this class Illuminate\Cache\RateLimiter that I think could be useful but have no idea how to use it yet. Can anyone point me to the right direct with this? So basically the request should "wait" and execute only if the 25 requests/minute limit hasn't been reached.

Thanks!

like image 555
Jjj Avatar asked Jun 29 '20 15:06

Jjj


People also ask

What is Ratelimiter in Laravel?

Laravel includes a simple to use rate limiting abstraction which, in conjunction with your application's cache, provides an easy way to limit any action during a specified window of time. If you are interested in rate limiting incoming HTTP requests, please consult the rate limiter middleware documentation.

How do I disable rate limiting in Laravel?

A: For disabling the rate limiter in Laravel, first go to the app/Http/Kernel. php. There you will find the default throttle limit defined by Laravel for all api routes. Just comment out that code to disable it completely.

How does Laravel rate limit work?

Laravel's rate limiting middleware stores the client's IP address alongside with the amount of requests in a given time period and performs a check on every request.

What is the default rate limiter value in Laravel?

The default throttle limits it to 60 attempts per minute, and disables their access for a single minute if they hit the limit.


1 Answers

The Illuminate\Cache\RateLimiter class has hit and tooManyAttempts methods you can use like this:

use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;

protected function sendRequest()
{
    if ($this->hasTooManyRequests()) {
        // wait
        sleep(
            $this->limiter()
                ->availableIn($this->throttleKey()) + 1 // <= optional plus 1 sec to be on safe side
        );

        // Call this function again.
        return $this->sendRequest();
    }
    
    //proceed to api call
    $response = apiCall();

    // Increment the attempts
    $this->limiter()->hit(
        $this->throttleKey(), 60 // <= 60 seconds
    );

    return $response;
}

/**
 * Determine if we made too many requests.
 *
 * @return bool
 */
protected function hasTooManyRequests()
{
    return $this->limiter()->tooManyAttempts(
        $this->throttleKey(), 25 // <= max attempts per minute
    );
}

/**
 * Get the rate limiter instance.
 *
 * @return \Illuminate\Cache\RateLimiter
 */
protected function limiter()
{
    return app(RateLimiter::class);
}

/**
 * Get the throttle key for the given request.
 *
 * @return string
 */
protected function throttleKey()
{
    return 'custom_api_request';
}

See Illuminate\Cache\RateLimiter class for more available methods.

You may also check Illuminate\Foundation\Auth\ThrottlesLogins as an example to figure out how to use Illuminate\Cache\RateLimiter class.

Note: The RateLimiter methods use seconds instead of minutes since Laravel >= 5.8 and got a major improvement on v8.x.

like image 163
Hafez Divandari Avatar answered Nov 15 '22 09:11

Hafez Divandari