Skip to content
This repository has been archived by the owner on Jan 17, 2022. It is now read-only.

Commit

Permalink
feat(swoole): Allow to change publicdir at runtime
Browse files Browse the repository at this point in the history
Usage:

```bash
$ bin/console s:s:r -s --public-dir=public
```
  • Loading branch information
k911 committed Sep 23, 2018
1 parent 3534ed0 commit c5a0c27
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 65 deletions.
24 changes: 17 additions & 7 deletions Command/ServerProfileCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,29 @@ final class ServerProfileCommand extends Command
*/
public function __construct(KernelInterface $kernel, HttpServer $server, HttpServerConfiguration $configuration, RequestHandlerInterface $driver)
{
parent::__construct();

$this->kernel = $kernel;
$this->server = $server;
$this->driver = $driver;
$this->configuration = $configuration;

parent::__construct();
}

/**
* @throws \Assert\AssertionFailedException
*
* @return string
*/
private function getDefaultPublicDir(): string
{
return $this->configuration->hasPublicDir() ? $this->configuration->getPublicDir() : \dirname($this->kernel->getRootDir()).'/public';
}

/**
* {@inheritdoc}
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
* @throws \Assert\AssertionFailedException
*/
protected function configure(): void
{
Expand All @@ -53,7 +64,8 @@ protected function configure(): void
->addArgument('requests', InputArgument::REQUIRED, 'Number of requests to handle by the server')
->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.')
->addOption('enable-static', null, InputOption::VALUE_NONE, 'Enables static files serving');
->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());
}

/**
Expand All @@ -78,10 +90,8 @@ protected function execute(InputInterface $input, OutputInterface $output): void
(int) ($input->getOption('port') ?? $this->configuration->getPort())
);

if (\filter_var($input->getOption('enable-static'), FILTER_VALIDATE_BOOLEAN)) {
$this->configuration->enableServingStaticFiles(
$this->configuration->hasPublicDir() ? $this->configuration->getPublicDir() : \dirname($this->kernel->getRootDir()).'/public'
);
if (\filter_var($input->getOption('serve-static'), FILTER_VALIDATE_BOOLEAN)) {
$this->configuration->enableServingStaticFiles($input->getOption('public-dir'));
}

$requestLimit = (int) $input->getArgument('requests');
Expand Down
28 changes: 19 additions & 9 deletions Command/ServerRunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,38 @@ final class ServerRunCommand extends Command
*/
public function __construct(KernelInterface $kernel, HttpServer $server, HttpServerConfiguration $configuration, RequestHandlerInterface $driver)
{
parent::__construct();

$this->kernel = $kernel;
$this->server = $server;
$this->driver = $driver;
$this->configuration = $configuration;

parent::__construct();
}

/**
* @throws \Assert\AssertionFailedException
*
* @return string
*/
private function getDefaultPublicDir(): string
{
return $this->configuration->hasPublicDir() ? $this->configuration->getPublicDir() : \dirname($this->kernel->getRootDir()).'/public';
}

/**
* {@inheritdoc}
*
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
* @throws \Assert\AssertionFailedException
*/
protected function configure(): void
{
$this->setName('swoole:server:run')
->setDescription('Runs a local swoole http server')
->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.')
->addOption('enable-static', null, InputOption::VALUE_NONE, 'Enables static files serving. Uses configured public directory or symfony default one.');
->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')
->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());
}

/**
Expand All @@ -74,10 +86,8 @@ protected function execute(InputInterface $input, OutputInterface $output): void
(int) ($input->getOption('port') ?? $this->configuration->getPort())
);

if (\filter_var($input->getOption('enable-static'), FILTER_VALIDATE_BOOLEAN)) {
$this->configuration->enableServingStaticFiles(
$this->configuration->hasPublicDir() ? $this->configuration->getPublicDir() : \dirname($this->kernel->getRootDir()).'/public'
);
if (\filter_var($input->getOption('serve-static'), FILTER_VALIDATE_BOOLEAN)) {
$this->configuration->enableServingStaticFiles($input->getOption('public-dir'));
}

$this->driver->boot([
Expand Down
12 changes: 6 additions & 6 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ public function getConfigTreeBuilder(): TreeBuilder
->max(65535)
->defaultValue(9501)
->end()
->enumNode('runningMode')
->enumNode('running_mode')
->defaultValue('process')
->values(['process', 'reactor'])
->values(['process', 'reactor', 'thread'])
->cannotBeEmpty()
->end()
->enumNode('socketType')
->enumNode('socket_type')
->cannotBeEmpty()
->defaultValue('sock_tcp_ipv4')
->values(['sock_tcp_ipv4', 'sock_tcp_ipv6', 'sock_udp_ipv4', 'sock_udp_ipv6', 'unix_dgram', 'unix_stream'])
->defaultValue('tcp')
->values(['tcp', 'tcp_ipv6', 'udp', 'udp_ipv6', 'unix_dgram', 'unix_stream'])
->end()
->booleanNode('sslEnabled')
->booleanNode('ssl_enabled')
->defaultFalse()
->treatNullLike(false)
->end()
Expand Down
34 changes: 11 additions & 23 deletions DependencyInjection/SwooleExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,26 @@ private function registerHttpServerConfiguration(array $config, ContainerBuilder
'static' => $static,
'host' => $host,
'port' => $port,
'runningMode' => $runningMode,
'socketType' => $socketType,
'sslEnabled' => $sslEnabled,
'running_mode' => $runningMode,
'socket_type' => $socketType,
'ssl_enabled' => $sslEnabled,
'settings' => $settings,
] = $config;

$staticFileServingStrategy = $static['strategy'];
if ('auto' === $static['strategy']) {
$static['strategy'] = $this->isDebugOrNotProd($container) ? 'advanced' : 'off';
}

if ($this->enableAdvancedStaticHandler($container, $staticFileServingStrategy)) {
if ('advanced' === $static['strategy']) {
$container->register(AdvancedStaticFilesServer::class)
->addArgument(new Reference(AdvancedStaticFilesServer::class.'.inner'))
->setAutowired(true)
->setPublic(false)
->setDecoratedService(RequestHandlerInterface::class, null, -60);

$settings['serve_static_files'] = false;
$settings['public_dir'] = $static['public_dir'];
}

if ('default' === $staticFileServingStrategy) {
$settings['serve_static_files'] = true;
$settings['public_dir'] = $static['public_dir'];
}
$settings['serve_static'] = $static['strategy'];
$settings['public_dir'] = $static['public_dir'];

if ('auto' === $settings['log_level']) {
$settings['log_level'] = $container->getParameter('kernel.debug') ? 'debug' : 'notice';
Expand Down Expand Up @@ -165,17 +162,8 @@ public function getConfiguration(array $config, ContainerBuilder $container): Co
return Configuration::fromTreeBuilder();
}

/**
* Determines whether advanced static handler should be enabled.
*
* @param ContainerBuilder $container
* @param string $strategy
*
* @return bool
*/
private function enableAdvancedStaticHandler(ContainerBuilder $container, string $strategy): bool
private function isDebugOrNotProd(ContainerBuilder $container): bool
{
return 'advanced' === $strategy ||
('auto' === $strategy && ($container->getParameter('kernel.debug') && 'prod' !== $container->getParameter('kernel.environment')));
return $container->getParameter('kernel.debug') && 'prod' !== $container->getParameter('kernel.environment');
}
}
86 changes: 66 additions & 20 deletions Server/HttpServerConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ final class HttpServerConfiguration
private const SWOOLE_HTTP_SERVER_CONFIGURATION = [
'reactor_count' => 'reactor_num',
'worker_count' => 'worker_num',
'serve_static_files' => 'enable_static_handler',
'serve_static' => 'enable_static_handler',
'public_dir' => 'document_root',
'log_file' => 'log_file',
'log_level' => 'log_level',
'pid_file' => 'pid_file',
];

private const SWOOLE_SERVE_STATIC = [
'off' => false,
'advanced' => false,
'default' => true,
];

private const SWOOLE_LOG_LEVELS = [
'debug' => SWOOLE_LOG_DEBUG,
'trace' => SWOOLE_LOG_TRACE,
Expand All @@ -42,12 +48,12 @@ final class HttpServerConfiguration
];

private const SWOOLE_SOCKET_TYPE = [
'sock_tcp_ipv4' => SWOOLE_SOCK_TCP,
'sock_tcp_ipv6' => SWOOLE_SOCK_TCP6,
'sock_udp_ipv4' => SWOOLE_SOCK_UDP,
'sock_udp_ipv6' => SWOOLE_SOCK_UDP6,
'sock_unix_dgram' => SWOOLE_SOCK_UNIX_DGRAM,
'sock_unix_stream' => SWOOLE_SOCK_UNIX_STREAM,
'tcp' => SWOOLE_SOCK_TCP,
'tcp_ipv6' => SWOOLE_SOCK_TCP6,
'udp' => SWOOLE_SOCK_UDP,
'udp_ipv6' => SWOOLE_SOCK_UDP6,
'unix_dgram' => SWOOLE_SOCK_UNIX_DGRAM,
'unix_stream' => SWOOLE_SOCK_UNIX_STREAM,
];

private const PORT_MAX_VALUE = 65535;
Expand Down Expand Up @@ -98,16 +104,28 @@ public function __construct(
}

/**
* @param string $host
* @param int $port
* @param string $runningMode
* @param string $socketType
* @param bool $sslEnabled
* @param string $host
* @param int $port
* @param null|string $runningMode
* @param null|string $socketType
* @param bool|null $sslEnabled
*
* @throws \Assert\AssertionFailedException
*/
public function changeSocket(string $host, int $port, string $runningMode = 'process', string $socketType = 'sock_tcp_ipv4', bool $sslEnabled = false): void
public function changeSocket(string $host, int $port, ?string $runningMode = null, ?string $socketType = null, ?bool $sslEnabled = null): void
{
if (null === $runningMode) {
$runningMode = $this->runningMode ?? 'process';
}

if (null === $socketType) {
$socketType = $this->socketType ?? 'tcp';
}

if (null === $sslEnabled) {
$sslEnabled = $this->sslEnabled ?? false;
}

Assertion::notBlank($host, 'Host cannot be blank.');
Assertion::between($port, self::PORT_MIN_VALUE, self::PORT_MAX_VALUE, 'Provided port value "%s" is not between 0 and 65535.');
Assertion::inArray($runningMode, \array_keys(self::SWOOLE_RUNNING_MODE));
Expand Down Expand Up @@ -140,10 +158,15 @@ public function changePort(int $port): void
*/
public function enableServingStaticFiles(string $publicDir): void
{
$this->setSettings([
'serve_static_files' => true,
$settings = [
'public_dir' => $publicDir,
]);
];

if ('off' === $this->settings['serve_static']) {
$settings['serve_static'] = 'default';
}

$this->setSettings($settings);
}

/**
Expand All @@ -156,8 +179,8 @@ private function validateSetting(string $key, $value): void
{
Assertion::keyExists(self::SWOOLE_HTTP_SERVER_CONFIGURATION, $key, 'There is no configuration mapping for setting "%s".');

if ('serve_static_files' === $key) {
Assertion::boolean($value, 'Serve static files setting must be a boolean');
if ('serve_static' === $key) {
Assertion::inArray($value, \array_keys(self::SWOOLE_SERVE_STATIC));
}

if ('public_dir' === $key) {
Expand Down Expand Up @@ -185,7 +208,7 @@ private function validateSettings(array $settings): void
$this->validateSetting($name, $value);
}

Assertion::false(isset($settings['serve_static_files']) && !isset($settings['public_dir']), 'Enabling static files serving requires providing "public_dir" setting.');
Assertion::false(isset($settings['serve_static']) && 'off' !== $settings['serve_static'] && !isset($settings['public_dir']), 'Enabling static files serving requires providing "public_dir" setting.');
}

/**
Expand Down Expand Up @@ -300,14 +323,22 @@ public function getSettings(): array
* @see \Swoole\Http\Server::set()
*
* @return array
*
* @todo create swoole settings transformer
*/
public function getSwooleSettings(): array
{
$swooleSettings = [];
foreach ($this->settings as $key => $setting) {
$swooleSettingKey = self::SWOOLE_HTTP_SERVER_CONFIGURATION[$key];
$swooleGetter = \sprintf('getSwoole%s', \str_replace('_', '', $swooleSettingKey));
$swooleSettings[$swooleSettingKey] = \method_exists($this, $swooleGetter) ? $this->{$swooleGetter}() : $setting;
if (\method_exists($this, $swooleGetter)) {
$setting = $this->{$swooleGetter}();
}

if (null !== $setting) {
$swooleSettings[$swooleSettingKey] = $setting;
}
}

return $swooleSettings;
Expand All @@ -322,4 +353,19 @@ public function getSwooleLogLevel(): int
{
return self::SWOOLE_LOG_LEVELS[$this->settings['log_level']];
}

/**
* @see getSwooleSettings()
*
* @return bool
*/
public function getSwooleEnableStaticHandler(): bool
{
return self::SWOOLE_SERVE_STATIC[$this->settings['serve_static']];
}

public function getSwooleDocumentRoot(): ?string
{
return 'default' === $this->settings['serve_static'] ? $this->settings['public_dir'] : null;
}
}

0 comments on commit c5a0c27

Please sign in to comment.