Repository navigation
Tracking issue: HTTP_PROXY/HTTPS_PROXY/NO_PROXY support in Node.js #57872
Description
Activity
cc @nodejs/undici @nodejs/http
I have been looking into support for the http(s) builtins but it seems a bit too convoluted if this is hooked into the existing socket pooling of the agent and we need to perform tunnelling over the socket, as the lifecycle of the socket is exposed through the agent interface as well, So I am planning to take a different approach and just bypass the pooling when proxies are used for tunneling (that seems to be what most existing solutions on npm are already doing in their custom agents, anyway, just in a more convoluted way to combat with the Node.js internal invariants)
Reacted by Carlos FuentesSo I did comment that pooling seems difficult to support, but I ended up finishing an implementation that works with pooling and it's passing tests of basic use cases and failure cases: https://github.com/joyeecheung/node/tree/http-agent-proxy-4/ - still need another pass to check that I am not leaking anything with the pooling and finish more tests before I open a PR though.
Reacted by Matteo Collina and Carlos FuentesStill moving along with the implementation and was trying to figure out how to implement the timeouts in tunnel establishment. From what I gathered the most intuitive handling is probably - follow the timeout in per-request option bag if there is one, then fallback to the agent timeout if there is one, otherwise just make it infinite like the normal default request options. There might be appetite for a separate timeout value for the tunnel, but then it seems niche (most npm packages I've seen either just uses default and goes infinite or inherit from request/agent options) so we could defer that to later if anyone actually wants it.
Reacted by Matteo Collina and Carlos FuentesAlmost finished the initial implementation, it currently has 36 proxy specific tests (most of the diff is tests). Ran all the other existing http/https tests through a minimal local proxy server to check that the proxy behavior is transparent:
NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://127.0.0.1:8000 HTTP_PROXY=http://127.0.0.1:8000 tools/test.py --timeout=20 "test/parallel/test-http*" [03:36|% 100|+ 622|- 79]: DoneMost of the failures are caused by the testing proxy server itself not being very transparent since I didn't put a lot of thought into it, or that the tests are expecting specific things (e.g. events, errors) that have to come from a server in the same process. Will do another pass to check the failures to make sure that it's at least not worse than user-land implementations, before I open a PR soon-ish - I think the agent API surface might still need some discussion in the PR, but the functionality is unlikely to change since it's pretty conventional.
Reacted by Johann Pardanaud and Carlos FuentesNODE_USE_ENV_PROXY=1
The rule/guideline is "no new environment variables," right?
--use-env-proxythat's accepted in NODE_OPTIONS?(node already has way too many switches IMO but that's a separate discussion.)
It's a bit too late: we already have shipped for the support in fetch. https://nodejs.org/api/cli.html#node_use_env_proxy1
Although in practice NODE_OPTIONS may also be somewhat tricky to concatenate or inherit especially when dealing with workers (#41103), and the worker is not necessarily controlled by those who need to enable the feature (e.g. a worker spawned by a library forget to or could not properly concatenate the CLI options, and that worker sends an unproxied request in an environment that needs a proxy, env vars tend to be handled more correctly since it's a flat object)
- added a commit that references this issue
on Jul 5, 2025 PR for initial implementation of proxy support in http/https.request and Agent #58980
- added a commit that references this issue
on Jul 8, 2025 - added 2 commits that reference this issue
on Jul 18, 2025 - added 2 commits that reference this issue
on Jul 21, 2025 from what I test this not works in the fetch api ? Is this intended or a bug ?
6 remaining items
- added 2 commits that reference this issue
on Sep 23, 2025 - added 2 commits that reference this issue
on Oct 18, 2025 I'd like to be able to control the proxy used per request via the fetch API.
This could look like any of the following:
- Include a
proxyEnvargument in the RequestInit argument to fetch - Allow creating an object with a
fetchmethod on it, which can be initialized to use different proxy settings (or instead of a function, return a closure with the same API as the global fetch method) - Expose undici's ProxyAgent, so that I can use that in the
dispatcherargument to fetch (Expose Undici's ProxyAgent and setGlobalDispatcher within Node #43187)
- Include a
- added a commit that references this issue
on Feb 17, 2026 - addedhttpIssues and PRs related to the http subsystem.Issues and PRs related to the http subsystem.
on Mar 2, 2026 github-actions commented
on Jul 20, 2026 on Jul 20, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 20, 2026 - removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 20, 2026 @joyeecheung I think this can be closed?
If this is closed, should I open a new issue for #57872 (comment) ?
- added a commit that references this issue
on Jul 29, 2026 Hi everyone. @joyeecheung, I’d especially appreciate your guidance on this.
Could I get your thoughts on some differences in
NO_PROXYbehavior?I've been looking into the differences between
node:http,fetch(), curl, and thisNO_PROXYproposal. There are two related problems:node:httpandfetch()behave differently within Node.js.- Node.js behavior differs from curl and from the proposed behavior.
The second problem is broader and needs a separate discussion about the intended Node.js contract and compatibility. I would like to start with the first one and make
node:httpandfetch()internally consistent.I ran live requests through separate local origin and proxy servers using
NODE_USE_ENV_PROXY=1onv27.0.0-pre(9f04fcd7) and found at least the following differences:DIRECTmeans that the request reached the origin directly.PROXYmeans that the request reached the proxy.
The table uses
example.comfor readability. The live runs usedlocaltest.me, which resolved to the local origin server.NO_PROXYvalue or actionRequest host node:httpfetch()example.comsub.example.comPROXY DIRECT *.example.comexample.comPROXY DIRECT .example.com:PORTsub.example.com:PORTPROXY DIRECT none.invalid example.comexample.comPROXY DIRECT *example.comDIRECT PROXY none.invalid,*example.comDIRECT PROXY 127.0.0.1-127.0.0.9127.0.0.1DIRECT PROXY [::1][::1]PROXY DIRECT [::1]:PORT[::1]:PORTPROXY DIRECT ::1:PORT[::1]:PORTDIRECT PROXY Change process.env.no_proxyfrom a non-match to a match after the first requestsame host PROXY -> PROXY PROXY -> DIRECT no_proxy=""together with matching uppercaseNO_PROXYmatching host DIRECT PROXY Some of these are edge cases, but the first row is a normal domain-matching case that users can reasonably encounter. I have opened draft PR #65617 for that case and plan to keep it narrowly scoped.
I expect there are more differences to find, and I would be happy to continue investigating and working through them. Before opening more individual fixes, I would like to understand where the behavior should be discussed and how maintainers would prefer the implementation work to be structured.
In particular:
- Is this tracking issue the right place to discuss the differences and decide the expected behavior, or would it be better to open a separate issue? If separate issues are preferred, should there be one issue for the overall
NO_PROXYcontract or one issue per behavioral difference? - This issue already has an item for sharing environment variable parsing and matching code between
fetch()and thehttp(s)implementation. Is a shared matcher still the preferred direction? - If so, where should that matcher live, given that
fetch()comes from Undici? For example, should it be an internal Node.js helper, something maintained in Undici and reused bynode:http, or another arrangement? - If sharing the implementation is not practical, would a shared table-driven conformance suite for both implementations be the preferred way to keep their behavior consistent?
There are also differences outside the matcher itself, such as environment-value selection and whether changes to
process.env.no_proxyare observed at runtime. I am not sure whether those should be part of the same discussion or treated separately.I'm ready to continue the investigation and implementation work once I understand where these decisions should be made and which architecture maintainers prefer. Thank you.
--use-env-proxytoNODE_OPTIONS#59100--use-env-proxybreaks WebSocket (ws library) long connections via http.request() interception #62054Some nice to haves (depend on whether there are volunteers that want to pick them up):
Old issues: #8381 #15620