Fix/global proxy dispatcher#516
Open
BingqingLyu wants to merge 2 commits intomainfrom
Open
Conversation
…d loopback bypass - Bootstrap undici EnvHttpProxyAgent at gateway startup when proxy env vars are detected (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY) - Normalize socks4/4a/4h/5/5h:// URLs to http:// for undici compat - Route ALL_PROXY fallback through both httpProxy and httpsProxy - Ensure loopback addresses (localhost, 127.0.0.1, [::1]) are always bypassed via NO_PROXY merging; preserve NO_PROXY=* wildcard - Success-latch prevents redundant re-installation while allowing retry after no-op or constructor failure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
HTTP_PROXY/HTTPS_PROXY/ALL_PROXY), because Node.js 22+'sglobalThis.fetch(undici) does not read proxy env vars by default, and the upstreamstreamSimplein@mariozechner/pi-aidoes not accept adispatcherparameter.curl -x) proves the proxy itself is fine.applyGlobalProxyDispatcher()insrc/infra/net/global-proxy.tsthat callssetGlobalDispatcher(new EnvHttpProxyAgent())early in gateway startup (after dotenv loading), making allglobalThis.fetchcalls proxy-aware. AddedALL_PROXY/socks5:///socks5h://normalization insrc/infra/net/proxy-env.ts. 17 unit tests.Change Type
Scope
Linked Issue/PR
User-visible / Behavior Changes
HTTP_PROXY,HTTPS_PROXY, orALL_PROXYenv vars are set, LLM inference requests now route through the proxy instead of timing out.[net/global-proxy] global undici dispatcher set to EnvHttpProxyAgent (via ...)log line appears at startup when proxy is active.ALL_PROXYwithsocks5://orsocks5h://is rewritten tohttp://for undici compatibility (most local proxy tools like Clash/V2Ray accept HTTP CONNECT on the same port).NO_PROXY/no_proxyexclusions are respected — localhost services (Ollama, browser control, canvas host) are not affected.Security Impact (required)
NoNoYes— existingglobalThis.fetchcalls are now routed through the user-configured proxy when env vars are set. No new outbound calls are introduced.NoNoYes, explain risk + mitigation: The proxy dispatcher only activates when the user explicitly sets proxy env vars.EnvHttpProxyAgentrespectsNO_PROXYexclusions, so internal/localhost traffic is unaffected. IfEnvHttpProxyAgentconstruction fails (e.g. malformed URL), the error is logged and the gateway continues with direct connections.Repro + Verification
Environment
HTTP_PROXY=http://127.0.0.1:7897 HTTPS_PROXY=http://127.0.0.1:7897 ALL_PROXY=socks5://127.0.0.1:7897Steps
env HTTP_PROXY="http://127.0.0.1:7897" HTTPS_PROXY="http://127.0.0.1:7897" openclaw gatewayExpected
[net/global-proxy] global undici dispatcher set to EnvHttpProxyAgent (via HTTP_PROXY)in startup logActual (before fix)
LLM request timed outerrors, even thoughcurl -x http://127.0.0.1:7897 https://generativelanguage.googleapis.com/...succeedsEvidence
Unit tests (17 cases, all passing):
Regression tests pass with zero regressions:
src/infra/net/proxy-fetch.test.ts— 7/7 passedsrc/infra/net/fetch-guard.ssrf.test.ts— 9/9 passedStartup log confirming proxy activation:
Human Verification
npm link(OpenClaw 2026.3.13, commit 2b46c4c)env OPENCLAW_DISABLE_BONJOUR=1 HTTP_PROXY="http://127.0.0.1:7897" HTTPS_PROXY="http://127.0.0.1:7897" ALL_PROXY="socks5://127.0.0.1:7897" openclaw gateway run --force[net/global-proxy] global undici dispatcher set to EnvHttpProxyAgent (via HTTP_PROXY)in startup logsocks5h://protocol variant (was broken by original regex, now fixed)ALL_PROXY-only configuration (noHTTP_PROXY/HTTPS_PROXYset)Review Conversations
Compatibility / Migration
YesNo— uses existing standard proxy env vars (HTTP_PROXY,HTTPS_PROXY,ALL_PROXY,NO_PROXY)NoFailure Recovery (if this breaks)
applyGlobalProxyDispatcher()call insrc/gateway/server.impl.ts(single line). Or simply unset proxy env vars — the function is a no-op without them.src/gateway/server.impl.ts(remove import + call)socks5://tohttp://will cause connection failures. Users would see fetch errors instead of timeouts.Risks and Mitigations
globalThis.fetchcalls process-wide.streamSimplewhich only usesglobalThis.fetch.EnvHttpProxyAgentrespectsNO_PROXYso internal traffic is excluded. The function is cooperative (skips if a proxy dispatcher is already installed) and idempotent.Comparison with existing open PRs
ProxyAgentinserver-startup.tsNO_PROXY; modifies Telegram codeEnvHttpProxyAgentinundici-global-dispatcher.tsALL_PROXY; only covers embedded runnerFiles changed
src/infra/net/global-proxy.ts— New module:applyGlobalProxyDispatcher()+ test reset helpersrc/infra/net/global-proxy.test.ts— 17 unit testssrc/infra/net/proxy-env.ts— AddedresolveAllProxyFallbackOptions(), SOCKS protocol normalization (builds onresolveEnvHttpProxyUrl/hasEnvHttpProxyConfiguredfrom Fix env proxy bootstrap for model traffic openclaw/openclaw#43248)src/gateway/server.impl.ts— Import and callapplyGlobalProxyDispatcher()afterreadConfigFileSnapshot()Relationship with openclaw#43248
openclaw#43248 (merged 2026-03-11) added
ensureGlobalUndiciEnvProxyDispatcher()inundici-global-dispatcher.ts, called inside the embedded runner'srunEmbeddedAttempt(). This PR complements it with two things openclaw#43248 does not cover:runEmbeddedAttempt()— per-run, embedded runner onlystartGatewayServer()— once at gateway startup, covers all fetch pathsglobalThis.fetch: LLM inference, heartbeat, web search, usage tracking, etc.ALL_PROXYsupportresolveAllProxyFallbackOptions()bridges undici'sEnvHttpProxyAgentgapsocks5://,socks5h://,socks4://rewritten tohttp://readConfigFileSnapshot()so.env-defined proxy vars are visibleThis PR reuses the
resolveEnvHttpProxyUrlandhasEnvHttpProxyConfiguredhelpers that openclaw#43248 added toproxy-env.ts, and addsresolveAllProxyFallbackOptions()on top for the ALL_PROXY/SOCKS gap.