|
| 1 | +/** |
| 2 | + * Proxy support (issue #119): honor HTTPS_PROXY / HTTP_PROXY / NO_PROXY. |
| 3 | + * |
| 4 | + * Node's built-in fetch (undici) deliberately ignores the proxy environment |
| 5 | + * variables, so behind a corporate or CI proxy every request dies with |
| 6 | + * `fetch failed` after a full retry cycle. Installing undici's |
| 7 | + * `EnvHttpProxyAgent` as the global dispatcher restores the conventional |
| 8 | + * behavior (including NO_PROXY exemptions) for every fetch the CLI makes. |
| 9 | + * |
| 10 | + * Only active when a proxy env var is actually present, so the default path |
| 11 | + * stays byte-identical and pays zero startup cost. Dependency note for |
| 12 | + * reviewers: this adds `undici` as an explicit runtime dependency (the same |
| 13 | + * engine Node already bundles); the alternative, a hand-rolled CONNECT |
| 14 | + * tunnel, would re-implement what undici ships and maintains. |
| 15 | + */ |
| 16 | +import type { Dispatcher } from 'undici'; |
| 17 | +import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici'; |
| 18 | + |
| 19 | +export interface ProxyDeps { |
| 20 | + env?: NodeJS.ProcessEnv; |
| 21 | + /** Dispatcher installer. Defaults to undici's setGlobalDispatcher. */ |
| 22 | + install?: (agent: Dispatcher) => void; |
| 23 | +} |
| 24 | + |
| 25 | +/** |
| 26 | + * Install the env-driven proxy dispatcher when any proxy variable is set |
| 27 | + * (both canonical upper-case and conventional lower-case spellings). |
| 28 | + * Returns whether an agent was installed (observable for tests/debugging). |
| 29 | + */ |
| 30 | +export function maybeInstallProxyAgent(deps: ProxyDeps = {}): boolean { |
| 31 | + const env = deps.env ?? process.env; |
| 32 | + const hasProxy = [env.HTTPS_PROXY, env.https_proxy, env.HTTP_PROXY, env.http_proxy].some( |
| 33 | + value => typeof value === 'string' && value.length > 0, |
| 34 | + ); |
| 35 | + if (!hasProxy) return false; |
| 36 | + const install = deps.install ?? setGlobalDispatcher; |
| 37 | + // EnvHttpProxyAgent reads HTTPS_PROXY/HTTP_PROXY/NO_PROXY itself, per |
| 38 | + // request, so NO_PROXY exemptions apply without extra plumbing here. |
| 39 | + install(new EnvHttpProxyAgent()); |
| 40 | + return true; |
| 41 | +} |
0 commit comments