Skip to content

Test that proxy support works, and say that SOCKS does not - #5

Merged
mattpodwysocki merged 1 commit into
mainfrom
proxy-guard
Sep 14, 2026
Merged

mattpodwysocki merged 1 commit into
mainfrom
proxy-guard

Conversation

@mattpodwysocki

Copy link
Copy Markdown
Contributor

Ported from mapbox-cli-private#137, which can no longer merge there now that oss/ is a submodule (#132).

Nothing was broken; this stops it breaking, and corrects two things I had asserted in the issue behind it.

The invariant

Nothing in src/ mentions a proxy. HTTPS_PROXY, HTTP_PROXY, ALL_PROXY and NO_PROXY work only because http::build never calls .no_proxy(), so reqwest's system-proxy detection applies. That matters most to the users least able to work around losing it, and a .no_proxy() added to fix something else — to stop a local proxy interfering with auth login's loopback redirect, say — would remove it with nothing failing.

tests/proxy.rs asserts the behaviour rather than the absence of the call: it stands up a fake proxy on a loopback port and checks the CLI asks it to CONNECT api.mapbox.com:443. A grep for no_proxy would pass just as well if the client were rebuilt elsewhere, or if a future reqwest changed its default.

Two things I had wrong

"Add reqwest's socks feature" would have been a no-op. In 0.12.28 the feature is declared socks = [] — empty. I enabled it and measured: no new crate in Cargo.lock, no socks package in cargo metadata, build unchanged. Shipping that one-line diff and calling it SOCKS support would have been the same mistake as looking only for x-request-id in #3 — a flag set, a claim made, nothing working. Not in this PR.

SOCKS does not fail silently. I had written that ALL_PROXY=socks5://… "fails without saying why". It says exactly why:

{"code":"request_failed","message":"Request failed: error sending request:
 client error (Connect): tunnel error: failed to create underlying
 connection: unsupported scheme socks5", …}

So the fix isn't a scheme check here. It's that remedy::for_transport named HTTPS_PROXY and NO_PROXY but not ALL_PROXY — the variable most likely to have caused it — and said nothing about SOCKS. It now names both, and the test pins the wording.

Two tests, not four

I wrote four and deleted two. Proving a positive needs only a loopback listener, and nothing leaves the machine. Proving the negatives — that HTTP_PROXY alone does not carry an https request, and that NO_PROXY exempts a host — means letting the request reach the real API, so those tests would put the internet in the suite in order to assert reqwest's behaviour rather than this crate's. Both are documented as prose instead, in README.md and docs/commands.md, where the HTTP_PROXY one is probably the likeliest proxy question this CLI will get:

HTTP_PROXY alone does not carry Mapbox requests. Every Mapbox base URL is https, and that variable applies to http URLs only.

What was measured

A throwaway harness stood up a fake HTTP proxy and a fake SOCKS5 proxy on loopback ports, each completing just enough of its protocol to learn which host was asked for:

Variable Proxy saw
HTTPS_PROXY=http://… CONNECT api.mapbox.com:443 HTTP/1.1 — honoured
ALL_PROXY=socks5://… nothing; request failed unsupported scheme socks5
ALL_PROXY=socks5h://… nothing; same

Control: with no proxy variable the same command returns http_401 for a fake token, so the failures above are the proxy and not the network.

541 tests, fmt and clippy clean.

The original PR also edited AGENTS.md, which has no counterpart here, so the note recording both measurements next to the client invariant stays in the private repo.

Nothing in `src/` mentions a proxy. `HTTPS_PROXY`, `HTTP_PROXY`, `ALL_PROXY`
and `NO_PROXY` work only because `http::build` never calls `.no_proxy()`, so
`reqwest`'s own system-proxy detection applies. That matters most to the
users least able to work around losing it, and a `.no_proxy()` added to fix
something else — to stop a local proxy interfering with `auth login`'s
loopback redirect, say — would remove it with nothing failing.

`tests/proxy.rs` asserts the behaviour rather than the absence of the call:
it stands up a fake proxy on a loopback port and checks the CLI asks it to
`CONNECT api.mapbox.com:443`. A grep for `no_proxy` would pass just as well
if the client were rebuilt elsewhere, or if a future `reqwest` changed its
default.

Two things measured rather than assumed:

**"Add reqwest's `socks` feature" would have been a no-op.** In 0.12.28 the
feature is declared `socks = []` — empty. Enabling it locks no new crate and
changes nothing, so shipping that and calling it SOCKS support would have
been a claim with nothing behind it.

**SOCKS does not fail silently.** `ALL_PROXY=socks5://…` reports
`unsupported scheme socks5`. So the fix is not a scheme check here: it is
that `remedy::for_transport` named `HTTPS_PROXY` and `NO_PROXY` but not
`ALL_PROXY`, the variable most likely to have caused it, and said nothing
about SOCKS. It now names both, and the test pins the wording.

Two tests, not four. Proving a positive needs only a loopback listener and
nothing leaves the machine. Proving that `HTTP_PROXY` alone does not carry an
https request, or that `NO_PROXY` exempts a host, means letting the request
reach the real API — which would put the internet in the test suite to assert
`reqwest`'s behaviour rather than this crate's. Both are documented as prose
in README and `docs/commands.md` instead.

Ported from mapbox/mapbox-cli-private#137, which cannot merge there now that
`oss/` is a submodule (mapbox/mapbox-cli-private#132). That PR also edited
`AGENTS.md`, which has no counterpart here, so those notes stay private.
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.

2 participants