This commit is contained in:
Marek
2026-03-24 00:04:55 +01:00
commit c5229e48ed
4225 changed files with 511461 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
<?php
/*
* This file is part of the NelmioCorsBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\CorsBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Compiler pass for the nelmio_cors.configuration.provider tag.
*/
class CorsConfigurationProviderPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->hasDefinition('nelmio_cors.options_resolver')) {
return;
}
$resolverDefinition = $container->getDefinition('nelmio_cors.options_resolver');
$optionsProvidersByPriority = [];
foreach ($container->findTaggedServiceIds('nelmio_cors.options_provider') as $taggedServiceId => $tagAttributes) {
foreach ($tagAttributes as $attribute) {
$priority = isset($attribute['priority']) ? (int) $attribute['priority'] : 0;
$optionsProvidersByPriority[$priority][] = new Reference($taggedServiceId);
}
}
if (count($optionsProvidersByPriority) > 0) {
$resolverDefinition->setArguments(
[$this->sortProviders($optionsProvidersByPriority)]
);
}
}
/**
* Transforms a two-dimensions array of providers, indexed by priority, into a flat array of Reference objects
* @param array<int, list<Reference>> $providersByPriority
* @return Reference[]
*/
protected function sortProviders(array $providersByPriority): array
{
ksort($providersByPriority);
return call_user_func_array('array_merge', $providersByPriority);
}
}

View File

@@ -0,0 +1,216 @@
<?php
/*
* This file is part of the NelmioCorsBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\CorsBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition;
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('nelmio_cors');
$rootNode = $treeBuilder->getRootNode();
$rootNode
->children()
->arrayNode('defaults')
->addDefaultsIfNotSet()
->append($this->getAllowCredentials(true))
->append($this->getAllowOrigin())
->append($this->getAllowHeaders())
->append($this->getAllowMethods())
->append($this->getAllowPrivateNetwork(true))
->append($this->getExposeHeaders())
->append($this->getMaxAge())
->append($this->getHosts())
->append($this->getOriginRegex(true))
->append($this->getForcedAllowOriginValue())
->append($this->getSkipSameAsOrigin(true))
->end()
->arrayNode('paths')
->useAttributeAsKey('path')
->normalizeKeys(false)
->prototype('array')
->append($this->getAllowCredentials())
->append($this->getAllowOrigin())
->append($this->getAllowHeaders())
->append($this->getAllowMethods())
->append($this->getAllowPrivateNetwork())
->append($this->getExposeHeaders())
->append($this->getMaxAge())
->append($this->getHosts())
->append($this->getOriginRegex())
->append($this->getForcedAllowOriginValue())
->append($this->getSkipSameAsOrigin())
->end()
->end()
;
return $treeBuilder;
}
private function getSkipSameAsOrigin(bool $withDefaultValue = false): BooleanNodeDefinition
{
$node = new BooleanNodeDefinition('skip_same_as_origin');
if ($withDefaultValue) {
$node->defaultTrue();
}
return $node;
}
private function getAllowCredentials(bool $withDefaultValue = false): BooleanNodeDefinition
{
$node = new BooleanNodeDefinition('allow_credentials');
if ($withDefaultValue) {
$node->defaultFalse();
}
return $node;
}
private function getAllowOrigin(): ArrayNodeDefinition
{
$node = new ArrayNodeDefinition('allow_origin');
$node
->beforeNormalization()
->always(function ($v) {
if ($v === '*') {
return ['*'];
}
return $v;
})
->end()
->prototype('scalar')->end()
;
return $node;
}
private function getAllowHeaders(): ArrayNodeDefinition
{
$node = new ArrayNodeDefinition('allow_headers');
$node
->beforeNormalization()
->always(function ($v) {
if ($v === '*') {
return ['*'];
}
return $v;
})
->end()
->prototype('scalar')->end();
return $node;
}
private function getAllowMethods(): ArrayNodeDefinition
{
$node = new ArrayNodeDefinition('allow_methods');
$node->prototype('scalar')->end();
return $node;
}
private function getAllowPrivateNetwork(bool $withDefaultValue = false): BooleanNodeDefinition
{
$node = new BooleanNodeDefinition('allow_private_network');
if ($withDefaultValue) {
$node->defaultFalse();
}
return $node;
}
private function getExposeHeaders(): ArrayNodeDefinition
{
$node = new ArrayNodeDefinition('expose_headers');
$node
->beforeNormalization()
->always(function ($v) {
if ($v === '*') {
return ['*'];
}
return $v;
})
->end()
->prototype('scalar')->end();
return $node;
}
private function getMaxAge(): ScalarNodeDefinition
{
$node = new ScalarNodeDefinition('max_age');
$node
->defaultValue(0)
->validate()
->ifTrue(function ($v) {
return !is_numeric($v);
})
->thenInvalid('max_age must be an integer (seconds)')
->end()
;
return $node;
}
private function getHosts(): ArrayNodeDefinition
{
$node = new ArrayNodeDefinition('hosts');
$node->prototype('scalar')->end();
return $node;
}
private function getOriginRegex(bool $withDefaultValue = false): BooleanNodeDefinition
{
$node = new BooleanNodeDefinition('origin_regex');
if ($withDefaultValue) {
$node->defaultFalse();
}
return $node;
}
private function getForcedAllowOriginValue(): ScalarNodeDefinition
{
$node = new ScalarNodeDefinition('forced_allow_origin_value');
$node->defaultNull();
return $node;
}
}

View File

@@ -0,0 +1,88 @@
<?php
/*
* This file is part of the NelmioCorsBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\CorsBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class NelmioCorsExtension extends Extension
{
public const DEFAULTS = [
'allow_origin' => [],
'allow_credentials' => false,
'allow_headers' => [],
'allow_private_network' => false,
'expose_headers' => [],
'allow_methods' => [],
'max_age' => 0,
'hosts' => [],
'origin_regex' => false,
'skip_same_as_origin' => true,
];
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$defaults = array_merge(self::DEFAULTS, $config['defaults']);
if ($defaults['allow_credentials'] && in_array('*', $defaults['expose_headers'], true)) {
throw new \UnexpectedValueException('nelmio_cors expose_headers cannot contain a wildcard (*) when allow_credentials is enabled.');
}
// normalize array('*') to true
if (in_array('*', $defaults['allow_origin'])) {
$defaults['allow_origin'] = true;
}
if (in_array('*', $defaults['allow_headers'])) {
$defaults['allow_headers'] = true;
} else {
$defaults['allow_headers'] = array_map('strtolower', $defaults['allow_headers']);
}
$defaults['allow_methods'] = array_map('strtoupper', $defaults['allow_methods']);
if ($config['paths']) {
foreach ($config['paths'] as $path => $opts) {
$opts = array_filter($opts);
if (isset($opts['allow_origin']) && in_array('*', $opts['allow_origin'])) {
$opts['allow_origin'] = true;
}
if (isset($opts['allow_headers']) && in_array('*', $opts['allow_headers'])) {
$opts['allow_headers'] = true;
} elseif (isset($opts['allow_headers'])) {
$opts['allow_headers'] = array_map('strtolower', $opts['allow_headers']);
}
if (isset($opts['allow_methods'])) {
$opts['allow_methods'] = array_map('strtoupper', $opts['allow_methods']);
}
$config['paths'][$path] = $opts;
}
}
$container->setParameter('nelmio_cors.map', $config['paths']);
$container->setParameter('nelmio_cors.defaults', $defaults);
$locator = new FileLocator(__DIR__.'/../Resources/config');
$loader = new Loader\PhpFileLoader($container, $locator);
$loader->load('services.php');
}
}