По какой-то непонятной мне причине, в symfony до сих пор нет внятной механики rate limiter на атрибутах. Чтож, значит надо лепить свой велосипед! https://symfony.com/doc/current/rate_limiter.html - устанавливаем компонент, настраиваем. `php

namespace AppEventListenerRateLimit;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD)] class RateLimit {} Создаём атрибут, которым будем метить роуты.

<code class="language-php"php

namespace AppEventListenerRateLimit;

use SymfonyComponentHttpKernelKernelEvents; use SymfonyComponentHttpKernelEventResponseEvent; use SymfonyComponentHttpKernelEventControllerEvent; use SymfonyComponentRateLimiterRateLimiterFactoryInterface; use SymfonyComponentEventDispatcherAttributeAsEventListener; use SymfonyComponentHttpKernelExceptionTooManyRequestsHttpException;

#[AsEventListener(KernelEvents::CONTROLLER)] #[AsEventListener(KernelEvents::RESPONSE)] class RateLimitListener { private array $headers = [];

public function __construct( private RateLimiterFactoryInterface $mainLimiter, ) {}

public function onKernelController(ControllerEvent $evt): void { $reflector = $evt-getControllerReflector(); $attributes = $reflector->getAttributes(RateLimit::class);

if (empty($attributes)) { return; }

$request = $evt->getRequest(); $limiter = $this->mainLimiter->create( sprintf( '%s:$s', $request->getClientIp(), $request->attributes->get('_route'), ) ); $limit = $limiter->consume();

$this->headers = [ 'X-RateLimit-Remaining' => $limit->getRemainingTokens(), 'X-RateLimit-Retry-After' => $limit->getRetryAfter()->getTimestamp() - time(), 'X-RateLimit-Limit' => $limit->getLimit(), ];

if (true === $limit->isAccepted()) { return; }

throw new TooManyRequestsHttpException(); }

public function onKernelResponse(ResponseEvent $evt): void { if (empty($this->headers)) { return; }

$evt->getResponse()->headers->add($this->headers); } } Добавляем листенер. Я рейт лимит вешаю на связку ip+route. Можно это дело вынести на настройки в атрибуте.

`#[Route('/test', methods: Request::METHOD_GET)] #[RateLimit] public function test( #[MapRequestPayload()] IdentifierRequest $request, ): JsonResponse {``