http: match subdomains for plain NO_PROXY entries - #65617
Conversation
NO_PROXY=example.com only exact-matched the hostname in the http(s) builtins, so requests to subdomains still used the proxy. fetch() already matches the host and its subdomains. Reuse the existing suffix matcher (label boundary) for plain entries as well as leading-dot ones. Fixes: nodejs#65616 Assisted-by: Grok 4.6 Extra High Signed-off-by: Nikita Snetkov <lukyanish@gmail.com>
|
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #65617 +/- ##
==========================================
- Coverage 90.07% 90.06% -0.01%
==========================================
Files 751 751
Lines 254916 254918 +2
Branches 48133 48129 -4
==========================================
- Hits 229605 229588 -17
- Misses 16496 16498 +2
- Partials 8815 8832 +17
🚀 New features to boost your workflow:
|
| const suffix = entry.substring(1); | ||
| // Strip a leading "." if present, then match as a suffix with a | ||
| // label boundary. "*.example.com" is handled below (subdomains only). | ||
| if (!entry.startsWith('*.')) { |
There was a problem hiding this comment.
Could we limit suffix matching to domain entries?
As written, NO_PROXY=127.0.0.1 also bypasses foo.127.0.0.1, although IP entries are documented as exact matches. Empty entries from trailing commas can also match hostnames ending in a dot.
There was a problem hiding this comment.
Updated in the latest fixup to keep the change scoped to plain entries:
- The new suffix match ignores empty entries, so an empty entry from a
trailing comma cannot match a hostname ending in a dot. - It only applies when both the entry and request host are not IP
literals, soNO_PROXY=127.0.0.1does not matchfoo.127.0.0.1.
Existing leading-dot and wildcard behavior is unchanged. Both cases are
covered by regression tests.
|
|
||
| // The request should go through the proxy (not bypass it), | ||
| // because badexample.com is not a subdomain of example.com. | ||
| assert.match(stdout, /Status Code: 200/); |
There was a problem hiding this comment.
This test seems to pass whether the proxy is used or bypassed, since both paths reach the same server. Could we also assert that the custom lookup for badexample.com was not used?
For example:
assert.doesNotMatch(
stdout,
/Resolving lookup for badexample\.com/,
);
There was a problem hiding this comment.
Added it to all three negative blocks
Limit NO_PROXY suffix matching to domain entries and domain hosts: - drop empty entries (e.g. from trailing commas) at parse time, so they can no longer match hostnames ending with a dot - IP entries only match a host exactly; IP hosts can only be bypassed by exact IP, IP:port, or IP range entries - degenerate "." and "*." entries no longer match every host ending with a dot Assisted-by: Claude Fable 5 Signed-off-by: Nikita Snetkov <lukyanish@gmail.com>
Assert that the negative NO_PROXY domain tests actually go through the proxy: both paths return 200 from the same server, so assert on the absence of the custom lookup log line instead. Assisted-by: Claude Fable 5 Signed-off-by: Nikita Snetkov <lukyanish@gmail.com>
Reword the NO_PROXY IP-matching note: the previous wording contradicted the IP range and host:port forms listed above it. Assisted-by: Claude Fable 5 Signed-off-by: Nikita Snetkov <lukyanish@gmail.com>
af34dc3 to
8af581d
Compare
Keep the change scoped to plain domain entries. Preserve the existing leading-dot and wildcard behavior, while preventing the new suffix match from applying to empty entries or IP literals. Signed-off-by: Nikita Snetkov <lukyanish@gmail.com>
8af581d to
09d37d4
Compare
| @@ -4615,7 +4619,7 @@ Proxy URLs can use either HTTP or HTTPS protocols: | |||
| The `NO_PROXY` environment variable supports several formats: | |||
|
|
|||
| * `*` - Bypass proxy for all hosts | |||
| * `example.com` - Exact host name match | |||
| * `example.com` - Host and subdomain match (matches `sub.example.com`) | |||
| * `.example.com` - Domain suffix match (matches `sub.example.com`) | |||
There was a problem hiding this comment.
This would make example.com and .example.com match. This does not seem something we might want to do
NO_PROXY=example.comonly exact-matched the hostname in thehttp/httpsbuilt-ins, so requests to subdomains still used the proxy.Make plain domain entries match the host and its subdomains, as
fetch()already does, while preserving a label boundary.
The new plain-entry suffix match ignores empty entries and only applies
when both the entry and request host are not IP literals. Existing
leading-dot and wildcard behavior is unchanged.
Fixes: #65616
Refs: #57872
Assisted-by: Grok 4.6 Extra High
Assisted-by: Fable 5
cc @nodejs/http