Skip to content

Commit dddd936

Browse files
committed
use more "service oriented" implementation for the rate limiter
1 parent da4910e commit dddd936

5 files changed

Lines changed: 40 additions & 37 deletions

File tree

EventListener/RateLimitAnnotationListener.php

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
use Noxlogic\RateLimitBundle\Exception\RateLimitExceptionInterface;
1010
use Noxlogic\RateLimitBundle\LimitProcessorInterface;
1111
use Noxlogic\RateLimitBundle\Service\RateLimitService;
12-
use Noxlogic\RateLimitBundle\Util\AnnotationLimitProcessor;
13-
use Noxlogic\RateLimitBundle\Util\PathLimitProcessor;
1412
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1513
use Symfony\Component\HttpFoundation\Request;
1614
use Symfony\Component\HttpFoundation\Response;
@@ -31,23 +29,23 @@ class RateLimitAnnotationListener extends BaseListener
3129
protected $rateLimitService;
3230

3331
/**
34-
* @var \Noxlogic\RateLimitBundle\Util\PathLimitProcessor
32+
* @var LimitProcessorInterface
3533
*/
36-
protected $pathLimitProcessor;
34+
protected $limitProcessor;
3735

3836
/**
3937
* @param EventDispatcherInterface $eventDispatcher
4038
* @param RateLimitService $rateLimitService
41-
* @param PathLimitProcessor $pathLimitProcessor
39+
* @param LimitProcessorInterface $limitProcessor
4240
*/
4341
public function __construct(
4442
EventDispatcherInterface $eventDispatcher,
4543
RateLimitService $rateLimitService,
46-
PathLimitProcessor $pathLimitProcessor
44+
LimitProcessorInterface $limitProcessor
4745
) {
4846
$this->eventDispatcher = $eventDispatcher;
4947
$this->rateLimitService = $rateLimitService;
50-
$this->pathLimitProcessor = $pathLimitProcessor;
48+
$this->limitProcessor = $limitProcessor;
5149
}
5250

5351
/**
@@ -65,15 +63,7 @@ public function onKernelController(FilterControllerEvent $event)
6563
return;
6664
}
6765

68-
// Find the best match
69-
$annotations = $event->getRequest()->attributes->get('_x-rate-limit', array());
70-
71-
$limitProcessor = $this->pathLimitProcessor;
72-
if ($annotations) {
73-
$limitProcessor = new AnnotationLimitProcessor($annotations, $event->getController());
74-
}
75-
76-
$rateLimit = $limitProcessor->getRateLimit($event->getRequest());
66+
$rateLimit = $this->limitProcessor->getRateLimit($event->getRequest());
7767

7868
// Another treatment before applying RateLimit ?
7969
$checkedRateLimitEvent = new CheckedRateLimitEvent($event->getRequest(), $rateLimit);
@@ -85,7 +75,7 @@ public function onKernelController(FilterControllerEvent $event)
8575
return;
8676
}
8777

88-
$key = $this->getKey($limitProcessor, $rateLimit, $event->getRequest());
78+
$key = $this->getKey($rateLimit, $event);
8979

9080
$rateLimitInfo = $this->rateLimitService->getRateLimitInfo($key, $rateLimit);
9181
if (!$rateLimitInfo) {
@@ -139,7 +129,7 @@ protected function findBestMethodMatch(Request $request, array $annotations)
139129

140130
// Empty array, check the path limits
141131
if (count($annotations) == 0) {
142-
return $this->pathLimitProcessor->getRateLimit($request);
132+
return $this->limitProcessor->getRateLimit($request);
143133
}
144134

145135
$best_match = null;
@@ -160,13 +150,14 @@ protected function findBestMethodMatch(Request $request, array $annotations)
160150
return $best_match;
161151
}
162152

163-
private function getKey(LimitProcessorInterface $limitProcessor, RateLimit $rateLimit, Request $request)
153+
private function getKey(RateLimit $rateLimit, FilterControllerEvent $event)
164154
{
165155
// Let listeners manipulate the key
156+
$request = $event->getRequest();
166157
$keyEvent = new GenerateKeyEvent($request, '', $rateLimit->getPayload());
167158

168159
$keyEvent->addToKey(join('.', $rateLimit->getMethods()));
169-
$keyEvent->addToKey($limitProcessor->getRateLimitAlias($request));
160+
$keyEvent->addToKey($this->limitProcessor->getRateLimitAlias($request, $event->getController()));
170161

171162
$this->eventDispatcher->dispatch(RateLimitEvents::GENERATE_KEY, $keyEvent);
172163

LimitProcessorInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ public function getRateLimit(Request $request);
1515

1616
/**
1717
* @param Request $request
18+
* @param callable $controller
1819
* @return string
1920
*/
20-
public function getRateLimitAlias(Request $request);
21+
public function getRateLimitAlias(Request $request, callable $controller);
2122
}

Resources/config/services.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<parameter key="noxlogic_rate_limit.rate_limit_service.class">Noxlogic\RateLimitBundle\Service\RateLimitService</parameter>
1111
<parameter key="noxlogic_rate_limit.oauth_key_generate_listener.class">Noxlogic\RateLimitBundle\EventListener\OauthKeyGenerateListener</parameter>
1212
<parameter key="noxlogic_rate_limit.path_limit_processor.class">Noxlogic\RateLimitBundle\Util\PathLimitProcessor</parameter>
13+
<parameter key="noxlogic_rate_limit.annotation_limit_processor.class">Noxlogic\RateLimitBundle\Util\AnnotationLimitProcessor</parameter>
1314
</parameters>
1415

1516
<services>
@@ -23,14 +24,20 @@
2324
</call>
2425
</service>
2526

27+
<service alias="noxlogic_rate_limit.processor" id="noxlogic_rate_limit.annotation_limit_processor" public="true"/>
28+
29+
<service id="noxlogic_rate_limit.annotation_limit_processor" class="%noxlogic_rate_limit.annotation_limit_processor.class%" public="false">
30+
<argument id="noxlogic_rate_limit.path_limit_processor" type="service"/>
31+
</service>
32+
2633
<service id="noxlogic_rate_limit.path_limit_processor" class="%noxlogic_rate_limit.path_limit_processor.class%">
2734
<argument>%noxlogic_rate_limit.path_limits%</argument>
2835
</service>
2936

3037
<service id="noxlogic_rate_limit.rate_limit_annotation_listener" class="%noxlogic_rate_limit.rate_limit_annotation_listener.class%">
3138
<argument type="service" id="event_dispatcher" />
3239
<argument type="service" id="noxlogic_rate_limit.rate_limit_service" />
33-
<argument type="service" id="noxlogic_rate_limit.path_limit_processor" />
40+
<argument type="service" id="noxlogic_rate_limit.processor" />
3441

3542
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" priority="-10" />
3643

Util/AnnotationLimitProcessor.php

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@
99
class AnnotationLimitProcessor implements LimitProcessorInterface
1010
{
1111
/**
12-
* @var array
12+
* @var LimitProcessorInterface
1313
*/
14-
private $annotations;
14+
private $fallback;
1515

16-
/**
17-
* @var callable
18-
*/
19-
private $controller;
20-
21-
public function __construct(array $annotations, callable $controller)
16+
public function __construct(LimitProcessorInterface $fallback)
2217
{
23-
$this->annotations = $annotations;
24-
$this->controller = $controller;
18+
$this->fallback = $fallback;
2519
}
2620

2721
public function getRateLimit(Request $request)
2822
{
23+
$annotations = $request->attributes->get('_x-rate-limit', array());
24+
25+
if (!$annotations) {
26+
return $this->fallback->getRateLimit($request);
27+
}
28+
2929
$best_match = null;
30-
foreach ($this->annotations as $annotation) {
30+
foreach ($annotations as $annotation) {
3131
// cast methods to array, even method holds a string
3232
$methods = is_array($annotation->getMethods()) ? $annotation->getMethods() : array($annotation->getMethods());
3333

@@ -44,14 +44,18 @@ public function getRateLimit(Request $request)
4444
return $best_match;
4545
}
4646

47-
public function getRateLimitAlias(Request $request)
47+
public function getRateLimitAlias(Request $request, callable $controller)
4848
{
49+
$annotations = $request->attributes->get('_x-rate-limit', array());
50+
51+
if (!$annotations) {
52+
return $this->fallback->getRateLimitAlias($request, $controller);
53+
}
54+
4955
if (($route = $request->attributes->get('_route'))) {
5056
return $route;
5157
}
5258

53-
$controller = $this->controller;
54-
5559
if (is_string($controller) && false !== strpos($controller, '::')) {
5660
$controller = explode('::', $controller);
5761
}

Util/PathLimitProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function getMatchedPath(Request $request)
5656
return $this->getMatchedLimitPath($request);
5757
}
5858

59-
public function getRateLimitAlias(Request $request)
59+
public function getRateLimitAlias(Request $request, callable $controller)
6060
{
6161
return str_replace('/', '.', $this->getMatchedLimitPath($request));
6262
}

0 commit comments

Comments
 (0)