http: align empty proxy env var handling with fetch() - #66210
barathraj048 wants to merge 1 commit into
Conversation
Use nullish coalescing (??) instead of logical OR (||) when selecting between lower- and upper-cased proxy environment variables, matching the behavior already used by fetch()/Undici's EnvHttpProxyAgent. Previously, an explicit empty string in a lower-cased variable (e.g. http_proxy='') would be treated as falsy and silently fall back to the upper-cased variable in http.request(), while fetch() correctly treated the empty string as an explicit override. Fixes: nodejs#66202
|
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #66210 +/- ##
==========================================
- Coverage 90.29% 90.29% -0.01%
==========================================
Files 790 790
Lines 272529 272883 +354
Branches 52031 52112 +81
==========================================
+ Hits 246083 246400 +317
- Misses 16909 16937 +28
- Partials 9537 9546 +9
🚀 New features to boost your workflow:
|
|
Was this PR submitted by accident at this time? It seems to be related to issue #66202 that was submitted a few hours ago, however there is no Also there was a discussion in the issue #66202 with the issue submitter @christianaurichzm where they indicated they already had a patch ready and were waiting for some clarification on the direction to be taken. In the issue you wrote:
There isn't any follow-up in the issue that indicates you already submitted a PR. In terms of the PR itself, it's missing the Your commit must contain the It's also failing linting due to a missing new line at the end of the file. |
christianaurichzm
left a comment
There was a problem hiding this comment.
Some review notes, mostly on the test.
On the direction itself, #66202 is still waiting on a maintainer preference.
The same two lines in the other direction are the curl-aligned fix, so it may
be worth settling that before encoding one of the two readings.
| // See https://about.gitlab.com/blog/we-need-to-talk-no-proxy/#http_proxy-and-https_proxy | ||
| const proxyUrl = (protocol === 'https:') ? | ||
| (env.https_proxy || env.HTTPS_PROXY) : (env.http_proxy || env.HTTP_PROXY); | ||
| (env.https_proxy || env.HTTPS_PROXY) : (env.http_proxy ?? env.HTTP_PROXY); |
There was a problem hiding this comment.
This line still uses ||, so after the patch http_proxy='' and no_proxy='' override the upper-cased variable while https_proxy='' still falls back to HTTPS_PROXY. The doc change in this PR https://github.com/barathraj048/node-js/blob/371a26a772ba62d4e9bb07c7994aba62245fb0c5/doc/api/http.md?plain=1#L221 states that https_proxy behaves like the other two, so the code and the docs here disagree.
| usesProxyFetch = res.headers.get('x-via-proxy') === '1'; | ||
| } catch { /* direct connection refused is expected if no proxy used */ } | ||
|
|
||
| assert.strictEqual(usesProxyFetch, usesProxyRequest, |
There was a problem hiding this comment.
This assertion passes without the proxy ever being used. With the patch,
env.http_proxy ?? env.HTTP_PROXY selects '', parseProxyUrl() returns
null, both clients connect directly to http://localhost:1/, the connection
is refused for both, and the comparison is false === false.
Running the test on main with both http_proxy and HTTP_PROXY empty, which
reproduces that same state, and with a request counter added to the proxy
server, prints:
assertion passed; requests received by the proxy server: 0
So the proxy server this test sets up is never contacted, and the assertion
would hold with it removed.
| })(); | ||
| `; | ||
|
|
||
| const result = spawnSync(process.execPath, ['--use-env-proxy', '-e', script], { |
There was a problem hiding this comment.
spawnSync blocks the parent event loop, so the proxy server created above
cannot answer the child it is supposed to proxy for. Running this test on
main, without the patch, it does not fail, it hangs:
$ timeout 45 out/Release/node test/parallel/test-http-proxy-env-empty-value.js; echo $?
124In CI that is a job timeout rather than a test failure. On Windows the test
cannot express this case at all: environment variables are case-insensitive
there, so http_proxy and HTTP_PROXY collapse into a single value, which is
why the existing proxy tests skip these cases with common.isWindows.
| @@ -0,0 +1,52 @@ | |||
| 'use strict'; | |||
There was a problem hiding this comment.
The proxy tests live in test/client-proxy/ (72 of them), and
test/common/proxy-server.js already provides createProxyServer(),
checkProxiedRequest() and checkProxiedFetch(), which spawn the child
asynchronously and keep the servers responsive. test-http-proxy-fetch.mjs
there also shows the common.isWindows skip these cases need. The
common.hasCrypto check on L12 looks unnecessary as well: the only
client-proxy tests that need it are the TLS ones, and there is no TLS here.
|
Thanks @MikeMcC399 and @christianaurichzm for the careful review. You're right that I opened this before the direction in #66202 was settled, and I missed that @christianaurichzm already had a patch ready. The test issues you pointed out (the no-op assertion, spawnSync blocking the proxy server, and the missing Windows skip) are also valid, and I appreciate the pointers to test/client-proxy/ and the shared helpers. I'm closing this in favor of @christianaurichzm's work once a maintainer confirms the direction. Happy to help review or test that PR. |
|
Thank you for clarifying and closing this pull request! The pull request gives the impression that it was opened by an agent rather than a human. If this is the case, please note that this is forbidden by Node.js policies. These were linked in the first pull request #65952 you submitted. Please make sure that you read and understand the guidelines and policies if you are planning to submit future pull requests to this repo.
|
|
Thanks for the feedback. I'll carefully review the Node.js contributing guidelines and ensure future PRs are properly structured and thoroughly tested before submitting. |
|
@MikeMcC399 I genuinely appreciate you taking the time to point out the policies. I'm still learning the right way to contribute to Node.js and made a mistake here. If you ever have a spare 5 minutes, I would hugely appreciate a quick chat or some guidance on how I can improve and contribute properly in the future. I'd love to connect on LinkedIn if you are open to it: [https://www.linkedin.com/in/bharath-raj-7992a7248/] No pressure at all if you don't have the bandwidth, but thank you again for the review and the pointers! |
Refs: #66202
Status: Closed. The intended behavior is still being decided in #66202, and
@christianaurichzm has a fix prepared there.
This PR changed
lib/internal/http.jsto use??instead of||when choosingbetween the lower-cased and upper-cased proxy environment variables. With that
change, an explicitly empty lower-cased value (e.g.
http_proxy='') overridesthe upper-cased one instead of falling back to it. This matches how
fetch()(Undici's
EnvHttpProxyAgent) already behaves.Problems found in review, left here for reference:
http_proxyandno_proxywere switched to??.https_proxystillused
||, so the code did not match the updated docs.false === falseand would pass even without the proxy.spawnSync, which blocks the parent event loop, so it hangsinstead of failing. It also needed a
common.isWindowsskip and belongedin
test/client-proxy/, using the helpers intest/common/proxy-server.js.Signed-off-byline.