feat(browse): BROWSE_NO_PROXY env var to bypass system proxy on launch

On macOS, Chromium (via Playwright) inherits the system HTTP/S proxy by
default. When the user runs a local VPN/proxy app (Shadowrocket, ClashX,
Surge, etc.) that does TLS interception, Chromium's HTTPS handshake
breaks with SSL error 1 / net_error -100, and every goto fails with
ERR_ABORTED. The renderer then crashes and kills the browse server,
triggering the familiar '[browse] Starting server...' restart loop.

curl is unaffected because curl ignores the system proxy by default,
so curl-based health checks continue to pass while browse is broken —
making this failure mode especially confusing.

Opt-in: set BROWSE_NO_PROXY=1 in the environment and browse will pass
'--proxy-server=direct://' to Chromium at launch, bypassing the system
proxy entirely. Default behavior unchanged (still inherits system proxy)
so corporate proxy users are not affected.

Repro:
  # With Shadowrocket running in HTTP-proxy mode on macOS:
  browse goto https://example.com        # ERR_ABORTED / Timeout 15000ms
  BROWSE_NO_PROXY=1 browse goto https://example.com   # 200 OK
This commit is contained in:
quetaifu 2026-04-17 10:31:09 +08:00
parent 2300067267
commit 3c2adf81f0
1 changed files with 13 additions and 0 deletions

View File

@ -163,6 +163,19 @@ export class BrowserManager {
launchArgs.push('--no-sandbox');
}
// System proxy bypass: on macOS, Chromium inherits the system HTTP/S proxy
// by default. Local VPN/proxy apps (Shadowrocket, ClashX, Surge, etc.)
// typically MITM TLS via a local proxy — when the proxy's cert handling
// breaks, every Chromium navigation fails with net_error -100 /
// ERR_ABORTED and the renderer crashes, killing the browse server.
// Setting BROWSE_NO_PROXY=1 tells Chromium to route directly, bypassing
// the system proxy entirely. curl is unaffected by system proxy by
// default, so curl-based health checks can remain working while
// Chromium is broken — hence this needs to be explicit.
if (process.env.BROWSE_NO_PROXY === '1') {
launchArgs.push('--proxy-server=direct://');
}
if (extensionsDir) {
launchArgs.push(
`--disable-extensions-except=${extensionsDir}`,