Skip to content

Commit a203e8a

Browse files
feat: remove serveDirectory() — use serveFromDisk() for production
Drop the PHP built-in web server approach (serveDirectory) that caused firewall prompts and port conflicts on consumer PCs. serveFromDisk() is the correct production method — no ports, no extra processes, uses native platform URI schemes (phpgui:// on Linux, virtual host on Windows, loadFileURL on macOS). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e5043e7 commit a203e8a

1 file changed

Lines changed: 0 additions & 100 deletions

File tree

src/Widget/WebView.php

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ class WebView
2020
private string $id;
2121
private bool $debug;
2222

23-
/** @var resource|null PHP built-in server process for serveDirectory() */
24-
private $serverProcess = null;
25-
private ?int $serverPort = null;
26-
2723
/** @var array<string, callable> JS→PHP command handlers: name => callback(string $id, string $args) */
2824
private array $commandHandlers = [];
2925

@@ -86,74 +82,6 @@ public function setHtml(string $html): void
8682
$this->process->sendCommand(['cmd' => 'set_html', 'html' => $html]);
8783
}
8884

89-
/**
90-
* Serve a directory via PHP's built-in web server and navigate to it.
91-
*
92-
* Ideal for loading production frontend builds (e.g., Vite's dist/ folder).
93-
*
94-
* @param string $path Path to the directory containing index.html
95-
* @param int $port Port to use (0 = auto-pick a free port)
96-
*/
97-
public function serveDirectory(string $path, int $port = 0): void
98-
{
99-
$path = realpath($path);
100-
if (!$path || !is_dir($path)) {
101-
throw new \RuntimeException("Directory not found: {$path}");
102-
}
103-
if (!file_exists($path . '/index.html')) {
104-
throw new \RuntimeException("No index.html found in: {$path}");
105-
}
106-
107-
// Auto-pick a free port
108-
if ($port === 0) {
109-
$sock = @stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr);
110-
if (!$sock) {
111-
throw new \RuntimeException("Could not find a free port: {$errstr}");
112-
}
113-
$addr = stream_socket_get_name($sock, false);
114-
$port = (int) substr($addr, strrpos($addr, ':') + 1);
115-
fclose($sock);
116-
}
117-
118-
// Start PHP built-in server
119-
$cmd = sprintf(
120-
'%s -S 127.0.0.1:%d -t %s',
121-
PHP_BINARY,
122-
$port,
123-
escapeshellarg($path)
124-
);
125-
126-
$descriptors = [
127-
0 => ['pipe', 'r'],
128-
1 => ['pipe', 'w'],
129-
2 => ['pipe', 'w'],
130-
];
131-
132-
$this->serverProcess = proc_open($cmd, $descriptors, $pipes);
133-
if (!is_resource($this->serverProcess)) {
134-
throw new \RuntimeException("Failed to start local server on port {$port}");
135-
}
136-
$this->serverPort = $port;
137-
138-
// Close stdin, we don't need it
139-
fclose($pipes[0]);
140-
fclose($pipes[1]);
141-
fclose($pipes[2]);
142-
143-
// Wait for server to be ready (up to 3 seconds)
144-
$deadline = microtime(true) + 3.0;
145-
while (microtime(true) < $deadline) {
146-
$fp = @fsockopen('127.0.0.1', $port, $errno, $errstr, 0.1);
147-
if ($fp) {
148-
fclose($fp);
149-
break;
150-
}
151-
usleep(50000); // 50ms
152-
}
153-
154-
$this->navigate("http://127.0.0.1:{$port}");
155-
}
156-
15785
/**
15886
* Serve a directory directly via the native webview engine (no HTTP server).
15987
*
@@ -310,14 +238,6 @@ public function enableFetchProxy(): void
310238
JS);
311239
}
312240

313-
/**
314-
* Get the port of the local server started by serveDirectory().
315-
*/
316-
public function getServerPort(): ?int
317-
{
318-
return $this->serverPort;
319-
}
320-
321241
/* ── Window ──────────────────────────────────────────────────────────── */
322242

323243
/**
@@ -425,7 +345,6 @@ public function emit(string $event, mixed $payload = null): void
425345
*/
426346
public function destroy(): void
427347
{
428-
$this->stopServer();
429348
$this->process->close();
430349
}
431350

@@ -564,7 +483,6 @@ private function handleCommand(array $event): void
564483

565484
public function __destruct()
566485
{
567-
$this->stopServer();
568486
if (!$this->isClosed()) {
569487
$this->destroy();
570488
}
@@ -653,22 +571,4 @@ private function streamRequest(string $url, string $method, array $headers, ?str
653571
return [$status, $resHeaders, $resBody];
654572
}
655573

656-
private function stopServer(): void
657-
{
658-
if ($this->serverProcess && is_resource($this->serverProcess)) {
659-
$status = proc_get_status($this->serverProcess);
660-
if ($status['running']) {
661-
// Kill the server process tree
662-
$pid = $status['pid'];
663-
if (PHP_OS_FAMILY === 'Windows') {
664-
exec("taskkill /F /T /PID {$pid} 2>NUL");
665-
} else {
666-
exec("kill {$pid} 2>/dev/null");
667-
}
668-
}
669-
proc_close($this->serverProcess);
670-
$this->serverProcess = null;
671-
$this->serverPort = null;
672-
}
673-
}
674574
}

0 commit comments

Comments
 (0)