From ae21d8792b630842e2db2e818d571f03ce086d0c Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 03:02:57 +0300 Subject: [PATCH 1/7] Start server on the next free unoccupied port --- hyper-run | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/hyper-run b/hyper-run index 8e0f0b5..73f36c1 100755 --- a/hyper-run +++ b/hyper-run @@ -72,6 +72,33 @@ if (!$servers && !$secures) { exit(1); } +function startListener($master, $listener) +{ + $host = sprintf( + '%s://%s:%s', + $listener[2] ? 'https' : 'http', $listener[0], $listener[1] + ); + fwrite(STDOUT, "Development server started: <{$host}>\n"); + + try { + call_user_func_array([$master, 'addListener'], $listener); + } catch (React\Socket\ConnectionException $exception) { + $reason = 'Address already in use'; + + if (strpos($exception->getMessage(), $reason) === false) { + throw $exception; + } + + fwrite(STDERR, sprintf( + "Failed to listen on %s:%s (reason: %s)\n", + $listener[0], $listener[1], $reason + )); + + $listener[1] = (int) $listener[1] + 1; + startListener($master, $listener); + } +} + try { if (!ctype_digit($number) || $number < 1 || $number > 20) { @@ -116,13 +143,7 @@ try { $usedProcesses = $processes; $master = new mpyw\HyperBuiltinServer\Master($loop, $processes); foreach ($listeners as $listener) { - call_user_func_array([$master, 'addListener'], $listener); - - $host = sprintf( - '%s://%s:%s', - $listener[2] ? 'https' : 'http', $listener[0], $listener[1] - ); - fwrite(STDOUT, "Development server started: <{$host}>\n"); + startListener($master, $listener); } }) ->then(null, function ($e) use (&$usedProcesses) { From ec93011113d7b5f4bff17de44b87849f12471fa2 Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 18:24:44 +0300 Subject: [PATCH 2/7] Try to pick first unoccupied port only if port is not specified --- hyper-run | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hyper-run b/hyper-run index 73f36c1..8d12991 100755 --- a/hyper-run +++ b/hyper-run @@ -85,7 +85,9 @@ function startListener($master, $listener) } catch (React\Socket\ConnectionException $exception) { $reason = 'Address already in use'; - if (strpos($exception->getMessage(), $reason) === false) { + $isPortSpecified = $listener[4]; + + if ($isPortSpecified || strpos($exception->getMessage(), $reason) === false) { throw $exception; } @@ -119,8 +121,17 @@ try { $listeners = []; foreach ([$servers, $secures] as $type => $group) { + $isSecure = $type === 1; foreach ($group as $i => $server) { list($host, $port) = explode(':', $server, 2) + [1 => '']; + + if ($port === '') { + $port = $isSecure ? '44300' : '8000'; + $isPortSpecified = false; + } else { + $isPortSpecified = true; + } + $ip = filter_var(gethostbyname($host), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); $regex = '/\A(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\z/'; if ($ip === false || !preg_match($regex, $port)) { @@ -129,7 +140,7 @@ try { if (isset($listeners[$server])) { throw new \RuntimeException("Duplicated entry: $server"); } - $listeners[$server] = [$host, $port, $type === 1, $cert]; + $listeners[$server] = [$host, $port, $isSecure, $cert, $isPortSpecified]; } } From 3c59d70c9e3bce649a2f8818e9935b73e53e592e Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 20:33:55 +0300 Subject: [PATCH 3/7] Make 8000 & 44300 ports as default --- .travis.yml | 2 +- README.md | 30 +++++++++++++++++++++++------- hyper-run | 2 +- tests/unit/RemoteSimpleTest.php | 20 ++++++++++---------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 194711c..925e64f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ cache: - $HOME/.composer/cache script: - - ./hyper-run -S localhost:8080 -s localhost:8081 -n 5 -t examples & + - ./hyper-run -S localhost:8000 -s localhost:44300 -n 5 -t examples & - vendor/bin/codecept run unit - kill $! diff --git a/README.md b/README.md index f2018be..11a3cce 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Usage: hyper-run Example: - hyper-run -S localhost:8080 -s localhost:8081 + hyper-run -S localhost:8000 -s localhost:44300 [Required] -S ":" of an HTTP server. Multiple arguments can be accepted. @@ -54,18 +54,34 @@ Restrictions: mpyw@localhost:~$ ``` -## Example +### Quick start ```shell script -hyper-run -S localhost:8080 -s localhost:8081 -t src/app/www +hyper-run -S localhost -s localhost -t src/app/www ``` -It listens on +2 servers will start with the directory `src/app/www` as the document root: -- `http://localhost:8080` -- `https://localhost:8081` +- `http://localhost:8000` +- `https://localhost:44300` + +Servers start with first unoccupied port within range depending on a scheme. + +| Scheme | Default | Range | +| ------- | ------- | ----------- | +| `HTTP` | 8000 | 8000-8099 | +| `HTTPS` | 44300 | 44300-44399 | -using the directory `src/app/www` as the document root. +### Customize ports + +```shell script +hyper-run -S localhost:8080 -s localhost:4000 -t src/app/www +``` + +2 servers will start with the directory `src/app/www` as the document root: + +- `http://localhost:8080` +- `https://localhost:4000` ## Note for Windows users diff --git a/hyper-run b/hyper-run index 8d12991..a3e775b 100755 --- a/hyper-run +++ b/hyper-run @@ -30,7 +30,7 @@ Usage: $_SERVER[SCRIPT_NAME] Example: - $_SERVER[SCRIPT_NAME] -S localhost:8080 -s localhost:8081 + $_SERVER[SCRIPT_NAME] -S localhost:8000 -s localhost:44300 [Required] -S \":\" of an HTTP server. Multiple arguments can be accepted. diff --git a/tests/unit/RemoteSimpleTest.php b/tests/unit/RemoteSimpleTest.php index cfb70d5..71d7beb 100644 --- a/tests/unit/RemoteSimpleTest.php +++ b/tests/unit/RemoteSimpleTest.php @@ -53,55 +53,55 @@ private function curlsAssert200OK(array $curls) public function testSimple() { - Co::wait($ch = $this->curlInitWith('http://localhost:8080/upload_form.php')); + Co::wait($ch = $this->curlInitWith('http://localhost:8000/upload_form.php')); $this->curlAssert200OK($ch); } public function testSimpleSecure() { - Co::wait($ch = $this->curlInitWith('https://localhost:8081/upload_form.php')); + Co::wait($ch = $this->curlInitWith('https://localhost:44300/upload_form.php')); $this->curlAssert200OK($ch); } public function testDelayed() { - Co::wait($ch = $this->curlInitWith('http://localhost:8080/fast_hello.php')); + Co::wait($ch = $this->curlInitWith('http://localhost:8000/fast_hello.php')); $this->curlAssert200OK($ch); } public function testDelayedSecure() { - Co::wait($ch = $this->curlInitWith('https://localhost:8081/fast_hello.php')); + Co::wait($ch = $this->curlInitWith('https://localhost:44300/fast_hello.php')); $this->curlAssert200OK($ch); } public function testDelayedGroupSingle() { - Co::wait($chs = $this->curlsInitWith(5, 'http://localhost:8080/fast_hello.php')); + Co::wait($chs = $this->curlsInitWith(5, 'http://localhost:8000/fast_hello.php')); $this->curlsAssert200OK($chs); } public function testDelayedGroupSingleSecure() { - Co::wait($chs = $this->curlsInitWith(5, 'https://localhost:8081/fast_hello.php')); + Co::wait($chs = $this->curlsInitWith(5, 'https://localhost:44300/fast_hello.php')); $this->curlsAssert200OK($chs); } public function testDelayedGroupDouble() { - Co::wait($chs = $this->curlsInitWith(10, 'http://localhost:8080/fast_hello.php')); + Co::wait($chs = $this->curlsInitWith(10, 'http://localhost:8000/fast_hello.php')); $this->curlsAssert200OK($chs); } public function testDelayedGroupDoubleSecure() { - Co::wait($chs = $this->curlsInitWith(10, 'https://localhost:8081/fast_hello.php')); + Co::wait($chs = $this->curlsInitWith(10, 'https://localhost:44300/fast_hello.php')); $this->curlsAssert200OK($chs); } public function testDelayedGroupDoubleAtOnce() { - Co::wait($chs = $this->curlsInitWith(10, 'http://localhost:8080/fast_hello.php'), [ + Co::wait($chs = $this->curlsInitWith(10, 'http://localhost:8000/fast_hello.php'), [ 'concurrency' => 0, ]); $this->curlsAssert200OK($chs); @@ -109,7 +109,7 @@ public function testDelayedGroupDoubleAtOnce() public function testDelayedGroupDoubleAtOnceSecure() { - Co::wait($chs = $this->curlsInitWith(10, 'https://localhost:8081/fast_hello.php'), [ + Co::wait($chs = $this->curlsInitWith(10, 'https://localhost:44300/fast_hello.php'), [ 'concurrency' => 0, ]); $this->curlsAssert200OK($chs); From 473983e2e99a8e6ee431f86e483f5bc9c5b01f47 Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 20:37:48 +0300 Subject: [PATCH 4/7] Move quick start before the command reference --- README.md | 56 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 11a3cce..9b8fa90 100644 --- a/README.md +++ b/README.md @@ -27,33 +27,6 @@ Use **`vendor/bin/hyper-run`** as the execution path. ## Usage -```ShellSession -mpyw@localhost:~$ hyper-run -h - -Usage: - hyper-run - -Example: - hyper-run -S localhost:8000 -s localhost:44300 - -[Required] - -S ":" of an HTTP server. Multiple arguments can be accepted. - -s ":" of an HTTPS server. Multiple arguments can be accepted. - -[Optional] - -n The number of PHP built-in server clusters, from 1 to 20. Default is 10. - -t Path for the document root. Default is the current directory. - -r Path for the router script. Default is empty. - -c Path for the PEM-encoded certificate. - Default is "/Users/mpyw/.composer/vendor/mpyw/php-hyper-builtin-server/certificate.pem". - -Restrictions: - - The option -s is only supported on PHP 5.6.0 or later. - - Access logs will not be displayed on Windows. - -mpyw@localhost:~$ -``` - ### Quick start ```shell script @@ -83,6 +56,35 @@ hyper-run -S localhost:8080 -s localhost:4000 -t src/app/www - `http://localhost:8080` - `https://localhost:4000` +### Command Reference + +```ShellSession +mpyw@localhost:~$ hyper-run -h + +Usage: + hyper-run + +Example: + hyper-run -S localhost:8000 -s localhost:44300 + +[Required] + -S ":" of an HTTP server. Multiple arguments can be accepted. + -s ":" of an HTTPS server. Multiple arguments can be accepted. + +[Optional] + -n The number of PHP built-in server clusters, from 1 to 20. Default is 10. + -t Path for the document root. Default is the current directory. + -r Path for the router script. Default is empty. + -c Path for the PEM-encoded certificate. + Default is "/Users/mpyw/.composer/vendor/mpyw/php-hyper-builtin-server/certificate.pem". + +Restrictions: + - The option -s is only supported on PHP 5.6.0 or later. + - Access logs will not be displayed on Windows. + +mpyw@localhost:~$ +``` + ## Note for Windows users Unfortunately, `cmd.exe` has no option to run via shebang `#!/usr/bin/env php`, so you need to create the following batch file in the proper directory. From 66f7b40745a2f6fe69cae6c426b0fe8d7e8b10d4 Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 20:39:37 +0300 Subject: [PATCH 5/7] Add clickable links in README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9b8fa90..a898723 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ hyper-run -S localhost -s localhost -t src/app/www 2 servers will start with the directory `src/app/www` as the document root: -- `http://localhost:8000` -- `https://localhost:44300` +- [http://localhost:8000](http://localhost:8000) +- [https://localhost:44300](https://localhost:44300) Servers start with first unoccupied port within range depending on a scheme. @@ -53,8 +53,8 @@ hyper-run -S localhost:8080 -s localhost:4000 -t src/app/www 2 servers will start with the directory `src/app/www` as the document root: -- `http://localhost:8080` -- `https://localhost:4000` +- [http://localhost:8080](http://localhost:8080) +- [https://localhost:4000](https://localhost:4000) ### Command Reference From 1927323c392d1740e1d3bd58ef60929fefb1bac6 Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 20:40:41 +0300 Subject: [PATCH 6/7] Add clickable links in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a898723..3befa05 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ hyper-run -S localhost:8080 -s localhost:4000 -t src/app/www 2 servers will start with the directory `src/app/www` as the document root: -- [http://localhost:8080](http://localhost:8080) -- [https://localhost:4000](https://localhost:4000) +- http://localhost:8080 +- http://localhost:4000 ### Command Reference From 63de67babd078a374c9d2641c8eaae2b8fc69ddb Mon Sep 17 00:00:00 2001 From: antonkomarev Date: Tue, 2 Jun 2020 20:41:43 +0300 Subject: [PATCH 7/7] Undo clickable links --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3befa05..9b8fa90 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ hyper-run -S localhost -s localhost -t src/app/www 2 servers will start with the directory `src/app/www` as the document root: -- [http://localhost:8000](http://localhost:8000) -- [https://localhost:44300](https://localhost:44300) +- `http://localhost:8000` +- `https://localhost:44300` Servers start with first unoccupied port within range depending on a scheme. @@ -53,8 +53,8 @@ hyper-run -S localhost:8080 -s localhost:4000 -t src/app/www 2 servers will start with the directory `src/app/www` as the document root: -- http://localhost:8080 -- http://localhost:4000 +- `http://localhost:8080` +- `https://localhost:4000` ### Command Reference