Repository navigation
fix(cli): normalize proxy environment values httpx cannot parse - #160
Open
fenghonghao wants to merge 1 commit into
Open
fenghonghao wants to merge 1 commit into
fenghonghao wants to merge 1 commit into
Conversation
With a proxy configured, httpx <= 0.28.1 fails to build any client when the environment contains a socks:// proxy URL, or NO_PROXY entries such as [::1], ::1/128, fd00::/8 or a non-ASCII host name. Provider configure/test and model calls then fail with a misleading "Endpoint configuration error". At CLI startup, rewrite these values for the paos process only, following the workarounds used by other httpx-based projects: socks:// becomes socks5://, bracketed IPv6 entries lose their brackets, /128 entries become the address, and wider IPv6 ranges and non-ASCII host entries are dropped. Variable names match case-insensitively as in urllib, and NO_PROXY also accepts ';' separators. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
This branch has not been deployed
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.
Problem
With a proxy configured (
HTTP(S)_PROXY/ALL_PROXY), httpx 0.28.1 (the latest release) cannot construct anyClient/AsyncClientwhen the proxy environment contains one of these values:NO_PROXY=[::1],[fd00::1]:8080InvalidURL: Invalid port: ':1]'NO_PROXY=::1/128,fd00::/8(any IPv6 range)InvalidURL: Invalid port: ...NO_PROXY=中国.cn(non-ASCII host)InvalidURL: Invalid IDNA hostnameALL_PROXY=socks://127.0.0.1:7897ValueError: Unknown scheme for proxy URLhttpx turns every
NO_PROXYentry into a URL pattern: bracketed IPv6 falls through to the wildcard branch (all://*[::1]), IPv6 ranges are wrapped with their mask inside the brackets (all://[fd00::/8]), and host entries get a*prefix that IDNA rejects for non-ASCII names.In PhyAgentOS this breaks model discovery in
paos provider configure,paos provider test, and LLM calls (the openai SDK and LiteLLM also use httpx).describe_provider_errorreportsEndpoint configuration error; check API Base and API compatibility., which points users at API Base instead of their proxy environment, and the configure wizard refuses to save.Upstream: encode/httpx#2659 and encode/httpx#3741 (open); pydantic/httpx2#1242 (closed).
Fix
New
PhyAgentOS/utils/proxy.pywithnormalize_proxy_env(), called from thepaosTyper callback before any subcommand runs. It rewrites values for the current process only:socks://host:port(any case)socks5://host:portsocksiois already a dependency[::1],[fd00::1]:8080,[fe80::1%eth0]::1,fd00::1,fe80::1%eth0::1/128,[::1]/128::1/128is one address, so local IPv6 services keep bypassing the proxyfd00::/8,fe80::/10,::1/129NO_PROXYentries as host patterns, never as CIDR ranges, so these never bypassed anything in httpx; they only crashed it中国.cn,.中国.cn<local>, URL-form entriesVariable names match case-insensitively, as in
urllib.request.getproxies()(NO_PROXY,no_proxy,No_Proxy,Https_Proxy).NO_PROXYentries may be separated by,or;(Windows bypass-list format) and are rejoined with,without duplicates. Values that need no change are left as they are.Requests to dropped entries now use the proxy. System and proxy-tool settings are untouched, so other programs keep their behavior. Subprocesses started by the CLI (such as the verification service) inherit the normalized environment. Malformed values that cannot be repaired, such as
socks4://(unsupported by httpx) or a non-numeric port, still fail loudly.This follows the workarounds other httpx-based projects use: NousResearch/hermes-agent#131802 (merged; unbrackets IPv6, rewrites CIDR to the address, rewrites
socks://), MoonshotAI/kimi-cli#2000 (drops IPv6 ranges, rewritessocks://), and nexu-io/open-design#7283 (drops IPv6 ranges, unbrackets IPv6, splits on;, keeps IPv4 ranges).Docs
Added a Troubleshooting row to
docs/en/02-user-manual.mdanddocs/zh/02-user-manual.mdcovering the symptoms, the startup normalization, and that scripts importing PhyAgentOS directly (not throughpaos) must adjust these variables themselves.Tests
New
tests/test_proxy_env.py(42 tests, proxy variables cleared for each test):NO_PROXY,no_proxyandNo_Proxy.example.com,.corp,*.internal,10.0.0.0/8,[127.0.0.1],fe80::1%eth0,http://[::1]:8080,*) are unchanged.socks://in any case is rewritten inALL_PROXY,all_proxy,HTTPS_PROXY,http_proxyandHttps_Proxy;socks5://,socks5h://andhttp://URLs are unchanged.httpx.Client()builds after normalization andhttp://[::1]:8000/bypasses the proxy.paos provider listthroughCliRunnernormalizesNO_PROXY. This test fails if the callback call is removed.ruff checkpasses on the changed files. Full suite: 644 passed.Note on
tests/test_skill_runtime_manifest.py::test_static_package_index_resolves_direct_skill_and_node, reported in #159 as failing on the base commit: it fails onmainfor this same reason whenever the developer'sNO_PROXYcontains an IPv6 range, and passes once that entry is removed. The test does not go through the CLI entry, so run on its own in such an environment it still fails; in the full suite it passes because earlier CLI tests normalize the process environment.Manual check: with a real proxy environment whose
NO_PROXYincludes an IPv6 range, and again withNo_Proxy='localhost;[::1];中国.cn'plusHttps_Proxy=socks://127.0.0.1:7897,paos provider test deepseekwith a dummy key returnsAuthentication failed(the request reached the API) instead ofEndpoint configuration error.🤖 Generated with Claude Code