-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Closed
Description
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();
}
Aerendir