Repository navigation
feat(net-http): :ENV proxy resolution (http_proxy/https_proxy/no_proxy) - #198
Merged
Merged
Conversation
Net::HTTP's p_addr now defaults to MRI's :ENV, resolving the proxy from the environment at request time instead of leaving the instance proxy-less (the item deferred by #183). - p_addr :ENV / omitted -> resolve from the environment against the instance's scheme (@use_ssl) and target host; nil/false -> no proxy; an explicit host String -> that fixed proxy (unchanged). - http requests read http_proxy/HTTP_PROXY, https requests read https_proxy/HTTPS_PROXY; the resolved userinfo becomes the Proxy-Authorization credentials. - no_proxy/NO_PROXY (comma/space list of hosts, leading-dot or bare domain suffixes, host:port qualifiers and CIDRs/IPs) forces a direct connection, mirroring URI::Generic.use_proxy?. - CGI-safety: when REQUEST_METHOD is set, the attacker-controllable uppercase HTTP_PROXY is ignored and only the lowercase http_proxy is honored (MRI's find_proxy rule). - proxy?/proxy_address/proxy_port/proxy_user/proxy_pass reflect the effective (explicit or env-resolved) proxy. Proven end-to-end through the VM against in-process httptest proxies (plain-http routing, https CONNECT tunnelling, no_proxy bypass, nil opt-out, CGI-safety) plus unit coverage of the resolver and no_proxy matcher; 100% coverage on the new code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tannevaled
added a commit
that referenced
this pull request
Jul 7, 2026
Merge of main brought #198's TestNetHTTPEnvProxyCGISafety, whose first assertion (uppercase HTTP_PROXY under CGI is ignored ⇒ proxy? false) cannot hold on Windows: env vars are case-insensitive there, so HTTP_PROXY and http_proxy are the same variable and the attacker-controllable-form-is-ignored distinction is unrepresentable (main's own windows lane is red on this at 6d1fea1). Guard only that first assertion behind non-windows; the lowercase- honored assertion still runs everywhere and exercises the same REQUEST_METHOD/os.Getenv("http_proxy") path, so coverage stays 100% on all lanes. CGI is a unix deployment concern. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tannevaled
added a commit
that referenced
this pull request
Jul 7, 2026
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.
Completes the
Net::HTTPproxy work deferred by #183: a bare /:ENVp_addrnow resolves the proxy from the environment (MRI's default), instead of leaving the instance proxy-less.What changed
:ENVdefault —Net::HTTP.new(host, port)(and:ENVexplicitly) now opt into environment resolution at request time, keyed on the instance's scheme (@use_ssl) and target host.Net::HTTP.new(host, port, nil)stays a hard opt-out (no proxy even with the env set); an explicit host String is unchanged.http_proxy/HTTP_PROXY, https readshttps_proxy/HTTPS_PROXY. The proxy URL is parsed asscheme://[user:pass@]host:port(a scheme-lesshost:portis retried ashttp://), and any userinfo becomes theProxy-Authorizationcredentials.no_proxy/NO_PROXY— comma/space list of hosts, leading-dot or bare-domain suffixes,host:portqualifiers and CIDRs/IP literals; a match forces a direct connection. MirrorsURI::Generic.use_proxy?.REQUEST_METHODis set, the attacker-controllable uppercaseHTTP_PROXYis ignored and only lowercasehttp_proxyis honored (MRI'sfind_proxyrule).proxy?/proxy_address/proxy_port/proxy_user/proxy_passnow reflect the effective (explicit or env-resolved) proxy.Proof
End-to-end through the VM against in-process
httptestproxies: plain-http routing withProxy-Authorization, https CONNECT tunnelling viahttps_proxy,no_proxybypass,nilopt-out, and the CGI-safety split — plus unit coverage of the resolver and theno_proxymatcher.GOWORK=off go build/vet/test ./...green; 100% coverage on all new code.Deferred
MRI's DNS-based loopback bypass (
find_proxyresolves the target and skips the proxy for127.*/::1) is intentionally not replicated — it needs a live resolver and would make loopback-target tests non-hermetic.🤖 Generated with Claude Code