|
123 | 123 | use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
|
124 | 124 | use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
125 | 125 | use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface;
|
| 126 | +use Symfony\Component\RateLimiter\Limiter; |
| 127 | +use Symfony\Component\RateLimiter\LimiterInterface; |
| 128 | +use Symfony\Component\RateLimiter\Storage\CacheStorage; |
126 | 129 | use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
|
127 | 130 | use Symfony\Component\Routing\Loader\AnnotationFileLoader;
|
128 | 131 | use Symfony\Component\Security\Core\Security;
|
@@ -173,6 +176,7 @@ class FrameworkExtension extends Extension
|
173 | 176 | private $mailerConfigEnabled = false;
|
174 | 177 | private $httpClientConfigEnabled = false;
|
175 | 178 | private $notifierConfigEnabled = false;
|
| 179 | + private $lockConfigEnabled = false; |
176 | 180 |
|
177 | 181 | /**
|
178 | 182 | * Responds to the app.config configuration parameter.
|
@@ -405,10 +409,18 @@ public function load(array $configs, ContainerBuilder $container)
|
405 | 409 | $this->registerPropertyInfoConfiguration($container, $loader);
|
406 | 410 | }
|
407 | 411 |
|
408 |
| - if ($this->isConfigEnabled($container, $config['lock'])) { |
| 412 | + if ($this->lockConfigEnabled = $this->isConfigEnabled($container, $config['lock'])) { |
409 | 413 | $this->registerLockConfiguration($config['lock'], $container, $loader);
|
410 | 414 | }
|
411 | 415 |
|
| 416 | + if ($this->isConfigEnabled($container, $config['rate_limiter'])) { |
| 417 | + if (!interface_exists(LimiterInterface::class)) { |
| 418 | + throw new LogicException('Rate limiter support cannot be enabled as the RateLimiter component is not installed. Try running "composer require symfony/rate-limiter".'); |
| 419 | + } |
| 420 | + |
| 421 | + $this->registerRateLimiterConfiguration($config['rate_limiter'], $container, $loader); |
| 422 | + } |
| 423 | + |
412 | 424 | if ($this->isConfigEnabled($container, $config['web_link'])) {
|
413 | 425 | if (!class_exists(HttpHeaderSerializer::class)) {
|
414 | 426 | throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed. Try running "composer require symfony/weblink".');
|
@@ -2170,6 +2182,48 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
|
2170 | 2182 | }
|
2171 | 2183 | }
|
2172 | 2184 |
|
| 2185 | + private function registerRateLimiterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) |
| 2186 | + { |
| 2187 | + if (!$this->lockConfigEnabled) { |
| 2188 | + throw new LogicException('Rate limiter support cannot be enabled without enabling the Lock component.'); |
| 2189 | + } |
| 2190 | + |
| 2191 | + $loader->load('rate_limiter.php'); |
| 2192 | + |
| 2193 | + $locks = []; |
| 2194 | + $storages = []; |
| 2195 | + foreach ($config['limiters'] as $name => $limiterConfig) { |
| 2196 | + $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); |
| 2197 | + |
| 2198 | + if (!isset($locks[$limiterConfig['lock']])) { |
| 2199 | + $locks[$limiterConfig['lock']] = new Reference($limiterConfig['lock']); |
| 2200 | + } |
| 2201 | + $limiter->addArgument($locks[$limiterConfig['lock']]); |
| 2202 | + unset($limiterConfig['lock']); |
| 2203 | + |
| 2204 | + if (!isset($storages[$limiterConfig['storage']])) { |
| 2205 | + $storageId = $limiterConfig['storage']; |
| 2206 | + // cache pools are configured by the FrameworkBundle, so they |
| 2207 | + // exists in the scoped ContainerBuilder provided to this method |
| 2208 | + if ($container->has($storageId)) { |
| 2209 | + if ($container->findDefinition($storageId)->hasTag('cache.pool')) { |
| 2210 | + $container->register('limiter.storage.'.$storageId, CacheStorage::class)->addArgument(new Reference($storageId)); |
| 2211 | + $storageId = 'limiter.storage.'.$storageId; |
| 2212 | + } |
| 2213 | + } |
| 2214 | + |
| 2215 | + $storages[$limiterConfig['storage']] = new Reference($storageId); |
| 2216 | + } |
| 2217 | + $limiter->replaceArgument(1, $storages[$limiterConfig['storage']]); |
| 2218 | + unset($limiterConfig['storage']); |
| 2219 | + |
| 2220 | + $limiterConfig['id'] = $name; |
| 2221 | + $limiter->replaceArgument(0, $limiterConfig); |
| 2222 | + |
| 2223 | + $container->registerAliasForArgument($limiterId, Limiter::class, $name.'.limiter'); |
| 2224 | + } |
| 2225 | + } |
| 2226 | + |
2173 | 2227 | private function resolveTrustedHeaders(array $headers): int
|
2174 | 2228 | {
|
2175 | 2229 | $trustedHeaders = 0;
|
|
0 commit comments