Skip to content

Commit

Permalink
fix(PhpBuiltInServer) more robust port check
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Oct 20, 2023
1 parent df91259 commit 4cbb562
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 42 deletions.
47 changes: 13 additions & 34 deletions src/ManagedProcess/PhpBuiltInServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use lucatume\WPBrowser\Exceptions\RuntimeException;
use lucatume\WPBrowser\Utils\Arr;
use lucatume\WPBrowser\Utils\Filesystem;
use lucatume\WPBrowser\Utils\Ports;

class PhpBuiltInServer implements ManagedProcessInterface
{
Expand Down Expand Up @@ -64,16 +65,14 @@ public function doStart(): void
);
$process->setOptions(['create_new_console' => true]);
$process->start();
$confirmPort = $this->confirmServerRunningOnPort($process);
if ($confirmPort === null || !(is_numeric($confirmPort) && (int)$confirmPort > 0)) {
if (!$this->confirmServerRunningOnPort($process)) {
$error = new RuntimeException(
'Could not start PHP Built-in server: ' . $process->getErrorOutput(),
ManagedProcessInterface::ERR_START
);
$this->stop();
throw $error;
}
$this->port = (int)$confirmPort;
$this->process = $process;
}

Expand All @@ -82,42 +81,22 @@ public function getPort(): int
return $this->port;
}

private function confirmServerRunningOnPort(Process $process): ?int
private function confirmServerRunningOnPort(Process $process): bool
{
// Using curl, make sure the server is running, it can be in error, but it should answer HEAD requests.
$curl = curl_init("http://localhost:$this->port");

if ($curl === false) {
throw new RuntimeException(
"Could not check PHP Built-in server: curl resource not created.",
self::ERR_CHECK
codecept_debug('confirming ...');
if ($process->getErrorOutput() === '') {
$process->waitUntil(
static function (string $type, string $output): bool {
codecept_debug(sprintf('type: %s, output: %s', $type, $output));
return $type === Process::ERR && !empty($output);
}
);
}

curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 1000);
curl_setopt($curl, CURLOPT_TIMEOUT_MS, 1000);

for ($attempts = 0; $attempts < 30; $attempts++) {
curl_exec($curl);
$curlInfo = curl_getinfo($curl);

if (isset($curlInfo['http_code']) && $curlInfo['http_code'] !== 0) {
curl_close($curl);
return $this->port;
}

if ($process->getExitCode() !== null) {
curl_close($curl);
throw new RuntimeException(
"PHP Built-in server could not start: port already in use.",
self::ERR_PORT_ALREADY_IN_USE
);
}
if (stripos($process->getErrorOutput(), 'failed') !== false) {
return false;
}

return null;
return Ports::isPortOccupied($this->port);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,14 @@ public function should_start_on_random_port_if_not_specified(): void
public function should_throw_if_specified_port_already_in_use(): void
{
$port = Random::openLocalhostPort();
$previousProcess = new Process([
PHP_BINARY,
'-S',
"localhost:$port",
'-t',
__DIR__
]);
$previousProcess->start();

$previousServer = new PhpBuiltInServer(__DIR__, $port);
$previousServer->start();

// Remove the PID file to make sure the second server will attempt a start.
if (!unlink(PhpBuiltInServer::getPidFile())) {
throw new \RuntimeException('Could not delete PID file.');
}

$server = new PhpBuiltInServer(__DIR__, $port);

Expand Down

0 comments on commit 4cbb562

Please sign in to comment.