Mahe Krish
Mahe Krish

Reputation: 171

How to set the rate limiter dynamically in Laravel 8

I need to set the rate limiter dynamically in Laravel 8 based on the combination of parameters stored in a database table:

S.No Key Param 1 Param 2 Param 3 Rate limit
1 adx param_1_a param_2_d param_3_x 20
2 buz param_1_b param_2_u param_3_z 30
3 cfy param_1_c param_2_f param_3_y 40

and rate limiter code will be as follows:

protected function configureRateLimiting()
{
   RateLimiter::for('api', function (Request $request) {
      return [
        Limit::perMinute(rateLimit)->by(RateLimitKey)->response(function () {
        ...
        }),
        Limit::perMinute(rateLimit1)->by(RateLimitKey1)->response(function () {
        ...
        }),
      ];
   });
}

I need to add the rate limiter to the array returned in the above code.

RateLimit value will be the value of the column "Rate Limit" from database table.

RateLimitKey will the value with combination of the columns Key, Param 1, Param 2, Param 3 (e.g., key_param1_param2_param_3)

Need to add the rate limiter dynamically using the data retrieved from the database table.

I am not sure about how to proceed on adding the rate limiter in Laravel 8.

Upvotes: 1

Views: 847

Answers (1)

mrhn
mrhn

Reputation: 18916

You have the request in the context, so from here it is just about getting out the data from the DB. I'm assuming they are query parameters. Remember that this can be null, and needs to have a fallback.

DB::table('rate_limiting_table')
    ->where('key', $request->query('key'))
    ->where('param_1', $request->query('param_1'))
    ->where('param_2', $request->query('param_2'))
    ->where('param_3', $request->query('param_3'))
    ->first();

Since this would be executed on each HTTP request, i would suggest caching it.

$cacheKey = $request->query('key') . $request->query('param_1') . $request->query('param_2') . $request->query('param_3');
cache()->remember($cacheKey, 14400, function () { // cached for 4 hours
    return ... // your query
});

Putting all this logic together, it could look like this. With some minor clean code improvements.

const DEFAULT_RATE_LIMITING = 60;

protected function configureRateLimiting()
{
    RateLimiter::for('global', function (Request $request) {
        $rateLimiting = $this->getCacheRateLimiting();

        return $rateLimiting ? $rateLimiting->rate_limit : static::DEFAULT_RATE_LIMITING;
    });
}

private function getRateLimitingDatabase(): ?object 
{
    DB::table('rate_limiting_table')
        ->where('key', $request->query('key'))
        ->where('param_1', $request->query('param_1'))
        ->where('param_2', $request->query('param_2'))
        ->where('param_3', $request->query('param_3'))
        ->first();
}

private function getCacheRateLimiting(): ?object 
{
    // cached for 4 hours
    return cache()->remember($this->getRateLimitingCacheKey(), 14400, function () {
        return  $this->getRateLimitingDatabase();
    });
}

private function getRateLimitingCacheKey(): string
{
    return $request->query('key')
        . $request->query('param_1')
        . $request->query('param_2')
        . $request->query('param_3');
}

Upvotes: 2

Related Questions