Skip to content

[RateLimiter] It does not work with long intervals (1 month, 1 year) #42784

@Barvoj

Description

@Barvoj

Symfony version(s) affected: 5.3, but seems that it does not work in any newer version (5.4, 6.0).

Description
Rate limit does not work with long intervals (1 month, 1 year). 1 year is transformed to 0 seconds so it basically does not limit anything.

How to reproduce
Set rate limit 1 and interval 1 year. Send multiple requests - none of them is stopped.

framework:
    rate_limiter:
        anonymous_api:
            policy: 'fixed_window'
            limit: 1
            interval: '1 year'
// src/Controller/ApiController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
use Symfony\Component\RateLimiter\RateLimiterFactory;

class ApiController extends AbstractController
{
    public function index(Request $request, RateLimiterFactory $anonymousApiLimiter)
    {
        $limiter = $anonymousApiLimiter->create($request->getClientIp());
        if (false === $limiter->consume(1)->isAccepted()) {
            throw new TooManyRequestsHttpException();
        }
    }
}

Possible Solution

It is caused by https://github.com/symfony/rate-limiter/blob/d00d756e2c9f9c8cc7964c19e619bfe19702559a/Util/TimeUtil.php#L21-L28 because it uses only seconds, minutes, hours and days to compute number of seconds from DateInterval. It ignores months and years.

I suggest to deduct timestamps to compute number of seconds:

public static function dateIntervalToSeconds(\DateInterval $interval): int
{
    $now = new DateTimeImmutable();

    return $now->add($interval)->getTimestamp() - $now->getTimestamp();
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions