Skip to content

Honour HTTP(S)_PROXY and NO_PROXY for the Python and uv runtime downloads - #631

Closed
yangyang-duolingo wants to merge 2 commits into
heroku:mainfrom
yangyang-duolingo:fix-ureq-proxy-from-env
Closed

yangyang-duolingo wants to merge 2 commits into
heroku:mainfrom
yangyang-duolingo:fix-ureq-proxy-from-env

Conversation

@yangyang-duolingo

@yangyang-duolingo yangyang-duolingo commented Oct 8, 2026 •

Copy link
Copy Markdown

Description

Fixes #630.

ureq::get() (used for both the Python runtime download and the uv download, download_and_unpack_zstd_archive/download_and_unpack_nested_gzip_archive in src/utils.rs) ignores HTTP_PROXY/HTTPS_PROXY entirely — it uses the crate's default global Agent, which never looks at the environment unless told to.

Earlier revision of this PR tried fixing this by enabling ureq's proxy-from-env Cargo feature. That turned out to be unnecessary and insufficient:

  • Unnecessary: proxy-from-env only changes the default value AgentBuilder initializes try_proxy_from_env to. The setter (AgentBuilder::try_proxy_from_env()) and Proxy::try_from_system() are compiled in regardless of the feature flag, so calling the setter explicitly needs no Cargo.toml change at all.
  • Insufficient: ureq has no NO_PROXY support of its own (checked src/proxy.rs in 2.12.1 — Proxy::try_from_system() only ever reads ALL_PROXY/HTTPS_PROXY/HTTP_PROXY). Enabling the feature as a blanket default would've sent every request through the configured proxy unconditionally, with no way to bypass it for any host.

This revision instead builds a small per-request Agent via http_agent(): it checks the request's host against NO_PROXY/no_proxy (matching by exact host, subdomain, or a bare *) and only asks the agent to look at the proxy env vars when the host isn't excluded. Includes unit tests for both the URI-authority parsing and the NO_PROXY matching logic.

Verification steps

  • Confirmed via ureq 2.12.1 source (Cargo.toml, src/agent.rs, src/proxy.rs) that try_proxy_from_env()/Proxy::try_from_system() aren't gated by the proxy-from-env feature, and that try_from_system() has no NO_PROXY handling of its own
  • This exact implementation is already live and passing tests in our fork (linked above)
  • cargo test (all 49 non-Docker-dependent tests pass, including the two new ones) and cargo clippy --all-targets -- -D warnings (clean) in a freshly-installed local toolchain

The Python and uv runtime downloads (download_and_unpack_zstd_archive /
download_and_unpack_nested_gzip_archive in src/utils.rs) use ureq::get(),
which ignores HTTP_PROXY/HTTPS_PROXY entirely: ureq's environment-based
proxy detection is gated behind its own proxy-from-env Cargo feature, which
isn't part of ureq's default feature set and wasn't enabled here either.

proxy-from-env activates no additional optional dependencies (it's a plain
marker feature), so Cargo.lock needs no changes.

Fixes heroku#630
The proxy-from-env Cargo feature only toggles AgentBuilder's default for
try_proxy_from_env -- the underlying Proxy::try_from_system() and the
try_proxy_from_env() setter are unconditionally compiled in regardless of
the feature flag, so calling the setter explicitly needs no Cargo.toml
change at all.

More importantly, ureq has no NO_PROXY support of its own (confirmed against
2.12.1's src/proxy.rs): the previous approach would have sent every request
through the configured proxy unconditionally, with no way to bypass it for
any host. This adds a small NO_PROXY matcher (entries matched by exact host,
subdomain, or '*') so a host in NO_PROXY still connects directly, and tests
both the URI-authority parsing and the NO_PROXY matching logic directly.

Adapted from the same fix already written, tested, and merged in our
downstream fork (duolingo/buildpacks-python#18), which hit this exact issue
running behind a mandatory HTTP proxy with its own NO_PROXY exclusions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@yangyang-duolingo
yangyang-duolingo requested a review from a team as a code owner October 8, 2026 14:45
@yangyang-duolingo yangyang-duolingo changed the title Enable ureq's proxy-from-env feature Honour HTTP(S)_PROXY and NO_PROXY for the Python and uv runtime downloads Oct 8, 2026
@yangyang-duolingo yangyang-duolingo mentioned this pull request Oct 10, 2026
3 of 4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python runtime download ignores HTTP_PROXY/HTTPS_PROXY (ureq's proxy-from-env feature isn't enabled)

1 participant