Skip to content

Web server bundle #21039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 6, 2017
Merged

Web server bundle #21039

merged 10 commits into from
Jan 6, 2017

Conversation

fabpot
Copy link
Member

@fabpot fabpot commented Dec 23, 2016

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? yes
Deprecations? no
Tests pass? yes
Fixed tickets #21040
License MIT
Doc PR n/a

Moved the server:* commands to a new bundle. It makes them more easily discoverable and more decoupled. Discoverability is important when not using symfony/symfony. In that case, the commands are not available unless you have the symfony/process component installed. With a dedicated bundle, installing the bundle also installs the dependency, making the whole process easier.

Usage is the same as the current commands for basic usage:

To start a web server in the foreground:

bin/console server:run

To manage a background server:

bin/console server:start
bin/console server:stop
bin/console server:status

The big difference is that port is auto-determined if something is already listening on port 8000.

Usage is different if you pass options:

bin/console server:start 127.0.0.1:8888
bin/console server:stop # no need to pass the address again
bin/console server:status # no need to pass the address again

That's possible as the web server now stores its address in a pid file stored in the current directory.

{
$this
->setDefinition(array(
new InputArgument('addressport', InputArgument::OPTIONAL, 'The address to listen to (can be address:port, address, or port)', '127.0.0.1:8000'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: instead of addressport, we could call this uri because we accept schemes or not, IP address or hostnames, port numbers or not, etc. So this looks like a URI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would name this socket.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about address? Like WebServer does?


$callback = null;
$disableOutput = false;
if (OutputInterface::VERBOSITY_NORMAL > $output->getVerbosity()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means === QUIET, right ? If yes, it may be much more readable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

->isQuiet() ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

'You can either install it or use the "server:run" command instead.',
));

if ($io->ask('Do you want to execute <info>server:run</info> immediately? [Yn] ', true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by making true the default, it means that a non-interactive process will automatically fallback to server:run. Is it expected ? I don't think it is a good idea, as it switches to a long-lived command. I think this should be done only for interactive inputs (returning the failure exit code otherwise)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabpot what about this ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is like this on the current commands. So, I'm not sure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I've made a new commit to change the default value to false

->setDefinition(array(
new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing this option is a BC break. We should deprecate it instead (even though the class is moved elsewhere, it is the same API for people using the CLI)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introducing a new composer package with a deprecation by default, is probably a bad idea? It should be done from the framework bundle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never kept BC on CLI commands AFAIK.

}
}

return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer a string|null API than string|false. The absence of value is null, not a boolean

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

$this->env = $env;
}

public function run($router = null, $disableOutput = true, $callback = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be typehinted as callable ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,35 @@
{
"name": "symfony/web-server-bundle",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you forgot the replace rule for this package in the root

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"name": "symfony/web-server-bundle",
"type": "web-server-bundle",
"description": "Symfony WebServerBundle",
"keywords": [],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add some keywords for discoverability through the Packagist search

Copy link
Contributor

@mickaelandrieu mickaelandrieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great move, with hope it's a start for a more readable console in full edition.

2 questions : will this bundle be installed by default on Symfony 4?

How about a Symfony/web-server package and a bundle? A lot of frameworks and cmses can be interested to reuse this tiny but useful piece of code.

Merry Christmas Fabien :)

@nicolas-grekas nicolas-grekas added this to the 3.3 milestone Dec 26, 2016
@ro0NL
Copy link
Contributor

ro0NL commented Dec 26, 2016

I would not need really the commands by default, i guess.

What about moving WebServer to symfony/process. As it already uses that, there's no real dependency issue or so. PhpServerProcess?

public function __construct($address = '127.0.0.1:8000')
{
if (false !== strpos($address, ':')) {
list($this->hostname, $this->port) = explode(':', $address);
Copy link
Contributor

@sstok sstok Dec 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work when IPv6 is used.

The format for IPv6 should actually be [address]:port, eg. [::1]:8000

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@fabpot fabpot force-pushed the web-server-bundle branch 3 times, most recently from 66b1ee3 to 2a31515 Compare December 30, 2016 07:37
@fabpot
Copy link
Member Author

fabpot commented Jan 4, 2017

Auto-port detection has just been added. I've also updated the description to describe usage and differences with current commands.

@fabpot fabpot force-pushed the web-server-bundle branch from 69e6a02 to 62ec25b Compare January 4, 2017 19:15
@fabpot
Copy link
Member Author

fabpot commented Jan 5, 2017

ping @symfony/deciders

@nicolas-grekas
Copy link
Member

👍

@mickaelandrieu
Copy link
Contributor

Also, as the behavior have changed this need - at least - an issue to document it :)

$io = new SymfonyStyle($input, $output);
$server = new WebServer();
if ($server->isRunning($input->getOption('pidfile'))) {
$io->success('Web server still listening.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to show the address and port where the port is listening? Otherwise this command doesn't provide much help:

server-status

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

new InputArgument('addressport', InputArgument::OPTIONAL, 'The address to listen to (can be address:port, address, or port)', null),
new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
new InputOption('pidfile', '', InputOption::VALUE_REQUIRED, 'PID file', null),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

second argument should be null

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed everywhere

new InputArgument('addressport', InputArgument::OPTIONAL, 'The address to listen to (can be address:port, address, or port)', null),
new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
new InputOption('pidfile', '', InputOption::VALUE_REQUIRED, 'PID file', null),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help of the comment should explain the PID file IMO

@@ -0,0 +1,19 @@
Copyright (c) 2004-2016 Fabien Potencier
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2017 now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

$this->port = $address;
} else {
$this->hostname = $address;
$this->port = 80;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also find the best port ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, done

if (false !== $pos = strrpos($address, ':')) {
$this->hostname = substr($address, 0, $pos);
$this->port = substr($address, $pos + 1);
} elseif (ctype_digit($address)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check if the user is trying to use a privileged port (i.e. < 1024) ?

Otherwise, you'll end up with this error:

command-port-1

browser-port-1

if (null === $address) {
$this->address = '127.0.0.1';
$this->port = $this->findBestPort();
$address = $this->address.':'.$this->port;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should return here, or put this if in the same chain than others, to avoid parsing the address and port again

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


if (false !== $pos = strrpos($address, ':')) {
$this->hostname = substr($address, 0, $pos);
$this->port = substr($address, $pos + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we should care about this ... but negative ports are wrongly allowed too:

negative-port-number

@fabpot fabpot force-pushed the web-server-bundle branch from 62ec25b to a95c8e7 Compare January 5, 2017 19:35
$this->port = $this->findBestPort();
} elseif (false !== $pos = strrpos($address, ':')) {
$this->hostname = substr($address, 0, $pos);
$this->port = substr($address, $pos + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I don't know if we should care, but here the port can also be non-numeric:

non-numeric-port

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed that to only allow numeric values.

@javiereguiluz
Copy link
Member

👍

Status: reviewed

@fabpot
Copy link
Member Author

fabpot commented Jan 5, 2017

@javiereguiluz server:start command fixed when the web server is already running.

@fabpot fabpot force-pushed the web-server-bundle branch from 7e60729 to 427d5e4 Compare January 5, 2017 19:48
@fabpot fabpot force-pushed the web-server-bundle branch from 427d5e4 to 612bb7e Compare January 5, 2017 19:48
@fabpot fabpot force-pushed the web-server-bundle branch from 612bb7e to 961d1ce Compare January 5, 2017 19:49
@fabpot
Copy link
Member Author

fabpot commented Jan 5, 2017

All comments taken into account now.

@fabpot fabpot merged commit f39b327 into symfony:master Jan 6, 2017
fabpot added a commit that referenced this pull request Jan 6, 2017
This PR was squashed before being merged into the 3.3-dev branch (closes #21039).

Discussion
----------

Web server bundle

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21040
| License       | MIT
| Doc PR        | n/a

Moved the `server:*` commands to a new bundle. It makes them more easily discoverable and more decoupled. Discoverability is important when not using symfony/symfony. In that case, the commands are not available unless you have the symfony/process component installed. With a dedicated bundle, installing the bundle also installs the dependency, making the whole process easier.

Usage is the same as the current commands for basic usage:

To start a web server in the foreground:

```
bin/console server:run
```

To manage a background server:

```
bin/console server:start
bin/console server:stop
bin/console server:status
```

The big difference is that port is auto-determined if something is already listening on port 8000.

Usage is **different** if you pass options:

```
bin/console server:start 127.0.0.1:8888
bin/console server:stop # no need to pass the address again
bin/console server:status # no need to pass the address again
```

That's possible as the web server now stores its address in a pid file stored in the current directory.

Commits
-------

f39b327 [WebServerBundle] switched auto-run of server:start to off by default
961d1ce [WebServerBundle] fixed server:start when already running
126f4d9 [WebServerBundle] added support for port auto-detection
6f689d6 [WebServerBundle] changed the way we keep track of the web server
585d445 [WebServerBundle] tweaked command docs
fa7ebc5 [WebServerBundle] moved most of the logic in a new class
951a1a2 [WebServerBundle] changed wording
ac1ba77 made the router configurable via env vars
48dd2b0 removed obsolete check
132902c moved server:* command to a new bundle
@fabpot fabpot deleted the web-server-bundle branch January 7, 2017 00:34
nicolas-grekas added a commit that referenced this pull request Jan 12, 2017
…ands (xabbuh)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle] fix IPv6 address handling in server commands

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21039 (comment)
| License       | MIT
| Doc PR        |

This fixes #21039 (comment) as reported by @sstok for the existing commands by backporting @fabpot's patch from #21039.

Commits
-------

2bb4713 fix IPv6 address handling in server commands
symfony-splitter pushed a commit to symfony/framework-bundle that referenced this pull request Jan 12, 2017
…ands (xabbuh)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle] fix IPv6 address handling in server commands

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | symfony/symfony#21039 (comment)
| License       | MIT
| Doc PR        |

This fixes symfony/symfony#21039 (comment) as reported by @sstok for the existing commands by backporting @fabpot's patch from #21039.

Commits
-------

2bb4713 fix IPv6 address handling in server commands
@fabpot fabpot mentioned this pull request May 1, 2017
@ben29
Copy link
Contributor

ben29 commented May 31, 2017

what about add support for https ?

@stof
Copy link
Member

stof commented May 31, 2017

I don't think the PHP built-in webserver supports HTTPS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.