Skip to content

Add the possibility to bind ServeCommand to all interfaces#871

Open
giuscris wants to merge 1 commit into2.xfrom
feature/improved-serve-command
Open

Add the possibility to bind ServeCommand to all interfaces#871
giuscris wants to merge 1 commit into2.xfrom
feature/improved-serve-command

Conversation

@giuscris
Copy link
Member

@giuscris giuscris commented Mar 1, 2026

This pull request improves the usability of the ServeCommand by making it easier to bind the server to all network interfaces and providing clearer feedback when running in this mode. The changes also enhance the output by listing accessible remote addresses when the server is bound to a wildcard host.

Usability improvements:

  • The default host for the server has been changed from '127.0.0.1' to 'localhost', and new constants LOOPBACK_HOSTS and WILDCARD_HOSTS have been introduced to clarify host types.
  • The host argument description now explains that omitting the value will bind the server to all interfaces.
  • Argument parsing allows --host to be passed without a value, causing the server to bind to all interfaces (0.0.0.0).

Output enhancements:

  • When the server is bound to a wildcard host, the output now displays remote addresses for all local network IPs, making it easier for users to find the correct address for remote access.
  • A new helper method getLocalNetworkIps() was added to retrieve local network IP addresses, excluding loopback interfaces.

@giuscris giuscris added this to the 2.4.0 milestone Mar 1, 2026
@giuscris giuscris requested a review from Copilot March 1, 2026 20:59
@giuscris giuscris self-assigned this Mar 1, 2026
@giuscris giuscris added the enhancement New feature or request label Mar 1, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the ServeCommand developer server CLI to make it easier to bind to all network interfaces and to improve the startup output when running on a wildcard bind address.

Changes:

  • Changed the default bind host from 127.0.0.1 to localhost, and introduced LOOPBACK_HOSTS / WILDCARD_HOSTS constants to classify hosts.
  • Added support for passing --host without a value to bind to all interfaces (intended to map to 0.0.0.0).
  • When bound to a wildcard host, the command now prints “Remote address” URLs for detected local network IPv4 addresses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +102 to +113
// Ignore parsing errors to handle passing `--host` without a value as a flag to bind to all interfaces
@$this->climate->arguments->parse();

if ($this->climate->arguments->get('help')) {
$this->climate->usage($argv);
exit(0);
}

/** @var string */
$host = $this->climate->arguments->get('host');
$host = $this->climate->arguments->defined('host')
? ($this->climate->arguments->get('host') ?: '0.0.0.0') // Bind to all interfaces if `--host` is passed without a value
: $this->host;
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

@ error suppression won’t prevent League\CLImate\Arguments::parse() from throwing InvalidArgumentException (as other commands already expect/catch), so --host passed without a value will likely still crash parsing. Also, parse() is called without $argv, meaning __invoke($argv) won’t be honored consistently. Consider passing $argv to parse() and handling the specific “missing value for --host” case via try/catch (or by pre-processing $argv to rewrite bare --host into --host=0.0.0.0), while still surfacing other parse errors to the user.

Copilot uses AI. Check for mistakes.
Comment on lines +368 to +382
if (($interfaces = net_get_interfaces()) === false) {
return [];
}

$localNetworkIps = [];

foreach ($interfaces as $interface) {
if (!isset($interface['unicast'])) {
continue;
}
foreach ($interface['unicast'] as $data) {
if (
$data['family'] === AF_INET // IPv4 addresses only
&& !in_array($data['address'], self::LOOPBACK_HOSTS, true) // Exclude loopback address
) {
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

net_get_interfaces() (and the AF_INET constant) require the sockets extension; the project doesn’t declare ext-sockets in composer requirements, so this can fatally error on systems without it (especially when binding to a wildcard host, which is now a supported path). Please guard with function_exists('net_get_interfaces') / defined('AF_INET') (or extension_loaded('sockets')) and return an empty list (or a helpful message) when unavailable.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants