From 686d39da62cce60f5db520888ad4ef489f64ddda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gangloff?= Date: Mon, 5 Aug 2024 22:05:32 +0200 Subject: [PATCH] feat: add Retry-After header if needed --- src/Controller/DomainRefreshController.php | 5 +++-- src/Controller/MeController.php | 24 +++++++++++++++++++--- src/Controller/RegistrationController.php | 14 ++++++++----- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/Controller/DomainRefreshController.php b/src/Controller/DomainRefreshController.php index ffe06c1..c8632de 100644 --- a/src/Controller/DomainRefreshController.php +++ b/src/Controller/DomainRefreshController.php @@ -64,12 +64,13 @@ class DomainRefreshController extends AbstractController if (false === $kernel->isDebug() && true === $this->getParameter('limited_features')) { $limiter = $this->rdapRequestsLimiter->create($userId); + $limit = $limiter->consume(); - if (false === $limiter->consume()->isAccepted()) { + if (false === $limit->isAccepted()) { $this->logger->warning('User {username} was rate limited by the API.', [ 'username' => $this->getUser()->getUserIdentifier(), ]); - throw new TooManyRequestsHttpException(); + throw new TooManyRequestsHttpException($limit->getRetryAfter()->getTimestamp() - time()); } } diff --git a/src/Controller/MeController.php b/src/Controller/MeController.php index c0fa651..20ca66e 100644 --- a/src/Controller/MeController.php +++ b/src/Controller/MeController.php @@ -3,12 +3,30 @@ namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\RateLimiter\RateLimiterFactory; +use Symfony\Component\Serializer\SerializerInterface; class MeController extends AbstractController { - public function __invoke(): UserInterface + public function __construct( + private readonly SerializerInterface $serializer, + private readonly RateLimiterFactory $rdapRequestsLimiter, + ) { + } + + public function __invoke(): Response { - return $this->getUser(); + $user = $this->getUser(); + $limiter = $this->rdapRequestsLimiter->create($user->getUserIdentifier()); + $limit = $limiter->consume(0); + + $data = $this->serializer->serialize($user, 'json', ['groups' => 'user:list']); + + return new JsonResponse($data, Response::HTTP_OK, [ + 'eu.domainwatchdog.ratelimiter.rdap.remaining' => $limit->getRemainingTokens(), + 'eu.domainwatchdog.ratelimiter.rdap.limit' => $limit->getLimit(), + ], true); } } diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php index 148cec6..f137da3 100644 --- a/src/Controller/RegistrationController.php +++ b/src/Controller/RegistrationController.php @@ -56,12 +56,16 @@ class RegistrationController extends AbstractController $limiter = $this->userRegisterLimiter->create($request->getClientIp()); - if (false === $this->kernel->isDebug() && false === $limiter->consume()->isAccepted()) { - $this->logger->warning('IP address {ip} was rate limited by the Registration API.', [ - 'ip' => $request->getClientIp(), - ]); + if (false === $this->kernel->isDebug()) { + $limit = $limiter->consume(); - throw new TooManyRequestsHttpException(); + if (false === $limit->isAccepted()) { + $this->logger->warning('IP address {ip} was rate limited by the Registration API.', [ + 'ip' => $request->getClientIp(), + ]); + + throw new TooManyRequestsHttpException($limit->getRetryAfter()->getTimestamp() - time()); + } } $user = $this->serializer->deserialize($request->getContent(), User::class, 'json', ['groups' => 'user:register']);