diff --git a/README.md b/README.md index 20ba4daf..76283b73 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,15 @@ Symfony integration with [Swoole](https://www.swoole.co.uk/) to speed up your ap parameters: env(HOST): localhost env(PORT): 9501 + env(TRUSTED_HOSTS): localhost,127.0.0.1 + env(TRUSTED_PROXIES): * swoole: http_server: port: '%env(int:PORT)%' host: '%env(HOST)%' + trusted_hosts: '%env(TRUSTED_HOSTS)%' + trusted_proxies: '%env(TRUSTED_PROXIES)%' ``` 4. Run swoole server diff --git a/composer.json b/composer.json index 0f04cc21..a325b386 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "extra": { "branch-alias": { - "dev-develop": "v0.1.x-dev" + "dev-develop": "v0.2.x-dev" } }, "config": { diff --git a/docs/configuration-reference.md b/docs/configuration-reference.md index 8a0a86d6..7ade3d7f 100644 --- a/docs/configuration-reference.md +++ b/docs/configuration-reference.md @@ -13,12 +13,14 @@ swoole: running_mode: 'process' socket_type: tcp ssl_enabled: false + trusted_hosts: localhost,127.0.0.1 + trusted_proxies: * static: strategy: 'advanced' public_dir: '%kernel.project_dir%/public' services: - debug: true - trust_all_proxies: true + debug_handler: true + trust_all_proxies_handler: true cloudfront_proto_header_handler: true entity_manager_handler: true settings: diff --git a/src/Bridge/Symfony/Bundle/Command/AbstractServerStartCommand.php b/src/Bridge/Symfony/Bundle/Command/AbstractServerStartCommand.php index fa6e86d2..9e547a10 100644 --- a/src/Bridge/Symfony/Bundle/Command/AbstractServerStartCommand.php +++ b/src/Bridge/Symfony/Bundle/Command/AbstractServerStartCommand.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use function K911\Swoole\decode_string_as_set; use function K911\Swoole\format_bytes; use function K911\Swoole\get_max_memory; @@ -24,27 +24,27 @@ abstract class AbstractServerStartCommand extends Command private $server; private $serverFactory; private $serverConfiguration; - private $kernel; private $bootManager; + private $parameterBag; /** * @param HttpServer $server * @param HttpServerFactory $serverFactory * @param HttpServerConfiguration $serverConfiguration - * @param KernelInterface $kernel + * @param ParameterBagInterface $parameterBag * @param BootManager $bootManager */ public function __construct( HttpServer $server, HttpServerFactory $serverFactory, HttpServerConfiguration $serverConfiguration, - KernelInterface $kernel, + ParameterBagInterface $parameterBag, BootManager $bootManager ) { $this->server = $server; $this->serverFactory = $serverFactory; $this->serverConfiguration = $serverConfiguration; - $this->kernel = $kernel; + $this->parameterBag = $parameterBag; $this->bootManager = $bootManager; parent::__construct(); @@ -57,7 +57,7 @@ public function __construct( */ private function getDefaultPublicDir(): string { - return $this->serverConfiguration->hasPublicDir() ? $this->serverConfiguration->getPublicDir() : \dirname($this->kernel->getRootDir()).'/public'; + return $this->serverConfiguration->hasPublicDir() ? $this->serverConfiguration->getPublicDir() : $this->parameterBag->get('kernel.project_dir').'/public'; } /** @@ -68,10 +68,14 @@ private function getDefaultPublicDir(): string */ protected function configure(): void { - $this->addOption('host', null, InputOption::VALUE_REQUIRED, 'Host name to listen to.') - ->addOption('port', null, InputOption::VALUE_REQUIRED, 'Range 0-65535. When 0 random available port is chosen.') + $defaultSocket = $this->serverConfiguration->getDefaultSocket(); + $this->addOption('host', null, InputOption::VALUE_REQUIRED, 'Host name to listen to.', $defaultSocket->host()) + ->addOption('port', null, InputOption::VALUE_REQUIRED, 'Range 0-65535. When 0 random available port is chosen.', $defaultSocket->port()) ->addOption('serve-static', 's', InputOption::VALUE_NONE, 'Enables serving static content from public directory.') - ->addOption('public-dir', null, InputOption::VALUE_REQUIRED, 'Public directory', $this->getDefaultPublicDir()); + ->addOption('public-dir', null, InputOption::VALUE_REQUIRED, 'Public directory', $this->getDefaultPublicDir()) + ->addOption('trusted-hosts', null, InputOption::VALUE_REQUIRED, 'Trusted hosts (e.g.: localhost,127.0.0.1)', $this->parameterBag->get('swoole.http_server.trusted_hosts')) + ->addOption('trusted-proxies', null, InputOption::VALUE_REQUIRED, 'Trusted proxies (e.g.: *,127.0.0.1)', $this->parameterBag->get('swoole.http_server.trusted_proxies')) + ; } /** @@ -129,10 +133,9 @@ private function ensureXdebugDisabled(): void */ protected function prepareServerConfiguration(HttpServerConfiguration $serverConfiguration, InputInterface $input): void { - $socket = $serverConfiguration->getDefaultSocket(); - $socket = $socket - ->withPort((int) ($input->getOption('port') ?? $socket->port())) - ->withHost((string) ($input->getOption('host') ?? $socket->host())); + $socket = $serverConfiguration->getDefaultSocket() + ->withPort((int) $input->getOption('port')) + ->withHost((string) $input->getOption('host')); $serverConfiguration->changeDefaultSocket($socket); @@ -149,8 +152,10 @@ protected function prepareServerConfiguration(HttpServerConfiguration $serverCon */ protected function prepareRuntimeConfiguration(HttpServerConfiguration $serverConfiguration, InputInterface $input): array { - $runtimeConfiguration['trustedHosts'] = decode_string_as_set($_SERVER['APP_TRUSTED_HOSTS']); - $runtimeConfiguration['trustedProxies'] = decode_string_as_set($_SERVER['APP_TRUSTED_PROXIES']); + $trustedHosts = $input->getOption('trusted-hosts'); + $trustedProxies = $input->getOption('trusted-proxies'); + $runtimeConfiguration['trustedHosts'] = \is_string($trustedHosts) ? decode_string_as_set($trustedHosts) : $trustedHosts; + $runtimeConfiguration['trustedProxies'] = \is_string($trustedProxies) ? decode_string_as_set($trustedProxies) : $trustedProxies; if (\in_array('*', $runtimeConfiguration['trustedProxies'], true)) { $runtimeConfiguration['trustAllProxies'] = true; @@ -176,8 +181,8 @@ protected function prepareRuntimeConfiguration(HttpServerConfiguration $serverCo protected function prepareConfigurationRowsToPrint(HttpServerConfiguration $serverConfiguration, array $runtimeConfiguration): array { $rows = [ - ['env', $this->kernel->getEnvironment()], - ['debug', \var_export($this->kernel->isDebug(), true)], + ['env', $this->parameterBag->get('kernel.environment')], + ['debug', \var_export($this->parameterBag->get('kernel.debug'), true)], ['worker_count', $serverConfiguration->getWorkerCount()], ['memory_limit', format_bytes(get_max_memory())], ['trusted_hosts', \implode(', ', $runtimeConfiguration['trustedHosts'])], diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php index ab82dec1..5f46b15b 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php @@ -6,6 +6,7 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; +use function K911\Swoole\decode_string_as_set; final class Configuration implements ConfigurationInterface { @@ -41,6 +42,26 @@ public function getConfigTreeBuilder(): TreeBuilder ->min(0) ->max(65535) ->defaultValue(9501) + ->beforeNormalization() + ->ifString() + ->then(function ($v): int { return (int) $v; }) + ->end() + ->end() + ->arrayNode('trusted_hosts') + ->defaultValue([]) + ->prototype('scalar')->end() + ->beforeNormalization() + ->ifString() + ->then(function ($v): array { return decode_string_as_set($v); }) + ->end() + ->end() + ->arrayNode('trusted_proxies') + ->defaultValue([]) + ->prototype('scalar')->end() + ->beforeNormalization() + ->ifString() + ->then(function ($v): array { return decode_string_as_set($v); }) + ->end() ->end() ->enumNode('running_mode') ->defaultValue('process') @@ -81,11 +102,11 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayNode('services') ->addDefaultsIfNotSet() ->children() - ->booleanNode('debug') + ->booleanNode('debug_handler') ->defaultFalse() ->treatNullLike(false) ->end() - ->booleanNode('trust_all_proxies') + ->booleanNode('trust_all_proxies_handler') ->defaultFalse() ->treatNullLike(false) ->end() diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/SwooleExtension.php b/src/Bridge/Symfony/Bundle/DependencyInjection/SwooleExtension.php index 68ceb487..962ad16d 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/SwooleExtension.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/SwooleExtension.php @@ -65,6 +65,9 @@ private function registerHttpServer(array $config, ContainerBuilder $container): $this->registerHttpServerServices($config['services'], $container); } + $container->setParameter('swoole.http_server.trusted_proxies', $config['trusted_proxies']); + $container->setParameter('swoole.http_server.trusted_hosts', $config['trusted_hosts']); + $this->registerHttpServerConfiguration($config, $container); } @@ -128,7 +131,7 @@ private function registerHttpServerServices(array $config, ContainerBuilder $con // RequestHandlerInterface // ------------------------- - if ($config['trust_all_proxies']) { + if ($config['trust_all_proxies_handler']) { $container->register(TrustAllProxiesRequestHandler::class) ->addArgument(new Reference(TrustAllProxiesRequestHandler::class.'.inner')) ->setAutowired(true) @@ -146,7 +149,7 @@ private function registerHttpServerServices(array $config, ContainerBuilder $con ->setDecoratedService(RequestHandlerInterface::class, null, -20); } - if ($config['debug'] || (null === $config['debug'] && $container->getParameter('kernal.debug'))) { + if ($config['debug_handler'] || (null === $config['debug_handler'] && $container->getParameter('kernel.debug'))) { $container->register(DebugHttpKernelRequestHandler::class) ->addArgument(new Reference(DebugHttpKernelRequestHandler::class.'.inner')) ->setAutowired(true) @@ -172,8 +175,13 @@ public function getConfiguration(array $config, ContainerBuilder $container): Co return Configuration::fromTreeBuilder(); } + private function isDebug(ContainerBuilder $container): bool + { + return $container->getParameter('kernel.debug'); + } + private function isDebugOrNotProd(ContainerBuilder $container): bool { - return $container->getParameter('kernel.debug') && 'prod' !== $container->getParameter('kernel.environment'); + return $this->isDebug($container) || 'prod' !== $container->getParameter('kernel.environment'); } } diff --git a/tests/Fixtures/Symfony/app/.env b/tests/Fixtures/Symfony/app/.env deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/Fixtures/Symfony/app/TestAppKernel.php b/tests/Fixtures/Symfony/app/TestAppKernel.php index bc5d9a91..713bffff 100644 --- a/tests/Fixtures/Symfony/app/TestAppKernel.php +++ b/tests/Fixtures/Symfony/app/TestAppKernel.php @@ -64,7 +64,7 @@ protected function configureRoutes(RouteCollectionBuilder $routes): void */ protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void { - $c->setParameter('kernel.project_dir', \dirname(__DIR__)); + $c->setParameter('kernel.project_dir', __DIR__); $confDir = __DIR__.'/config'; $loader->load($confDir.'/*'.self::CONFIG_EXTENSIONS, 'glob'); diff --git a/tests/Fixtures/Symfony/app/config/swoole.yaml b/tests/Fixtures/Symfony/app/config/swoole.yaml index 09f42cd2..7d296e8d 100644 --- a/tests/Fixtures/Symfony/app/config/swoole.yaml +++ b/tests/Fixtures/Symfony/app/config/swoole.yaml @@ -1,9 +1,10 @@ -parameters: - env(HOST): localhost - env(PORT): 9501 - swoole: http_server: - port: '%env(int:PORT)%' - host: '%env(HOST)%' - static: 'off' + port: 9501 + host: localhost + static: 'auto' + trusted_proxies: + - '*' + - 127.0.0.1/8 + - 192.168.2./16 + trusted_hosts: localhost,127.0.0.1 diff --git a/tests/Fixtures/Symfony/app/console b/tests/Fixtures/Symfony/app/console index 976671b6..d1fdec3d 100755 --- a/tests/Fixtures/Symfony/app/console +++ b/tests/Fixtures/Symfony/app/console @@ -14,9 +14,6 @@ if (!\class_exists(Application::class)) { throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.'); } -$_SERVER['APP_TRUSTED_HOSTS'] = '127.0.0.1,localhost'; -$_SERVER['APP_TRUSTED_PROXIES'] = '*'; - $input = new ArgvInput(); $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'test'); $debug = ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption(['--no-debug', '']); diff --git a/tests/Fixtures/Symfony/app/public/robots.txt b/tests/Fixtures/Symfony/app/public/robots.txt new file mode 100644 index 00000000..1f53798b --- /dev/null +++ b/tests/Fixtures/Symfony/app/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /