Skip to content

Commit abbc102

Browse files
committed
http: fix no_proxy leading-dot suffix matching
1 parent 56aba88 commit abbc102

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

lib/internal/http.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class ProxyConfig {
158158
// Follow curl's behavior: strip leading dot before matching suffixes.
159159
if (entry[0] === '.') {
160160
const suffix = entry.substring(1);
161-
if (host.endsWith(suffix)) return false;
161+
if (host === suffix || (host.endsWith(suffix) && host[host.length - suffix.length - 1] === '.')) return false;
162162
}
163163

164164
// Handle wildcards like *.example.com

test/client-proxy/test-http-proxy-request-no-proxy-domain.mjs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { runProxiedRequest } from '../common/proxy-server.js';
1010
const server = http.createServer(common.mustCall((req, res) => {
1111
res.writeHead(200, { 'Content-Type': 'text/plain' });
1212
res.end('Hello World\n');
13-
}, 3));
13+
}, 5));
1414
server.on('error', common.mustNotCall((err) => { console.error('Server error', err); }));
1515
server.listen(0, '127.0.0.1');
1616
await once(server, 'listening');
@@ -77,5 +77,42 @@ await once(proxy, 'listening');
7777
assert.strictEqual(code, 0);
7878
assert.strictEqual(signal, null);
7979
}
80+
81+
// Test NO_PROXY with leading-dot entry should NOT match partial domain names.
82+
// Regression test: .example.com must not match notexample.com or badexample.com.
83+
{
84+
const { code, signal, stderr, stdout } = await runProxiedRequest({
85+
NODE_USE_ENV_PROXY: 1,
86+
REQUEST_URL: `http://notexample.com:${server.address().port}/test`,
87+
HTTP_PROXY: `http://localhost:${server.address().port}`,
88+
RESOLVE_TO_LOCALHOST: 'notexample.com',
89+
NO_PROXY: '.example.com',
90+
});
91+
92+
// The request should go through the proxy (not bypass it),
93+
// because notexample.com is not a subdomain of example.com.
94+
assert.match(stdout, /Status Code: 200/);
95+
assert.strictEqual(stderr.trim(), '');
96+
assert.strictEqual(code, 0);
97+
assert.strictEqual(signal, null);
98+
}
99+
100+
{
101+
const { code, signal, stderr, stdout } = await runProxiedRequest({
102+
NODE_USE_ENV_PROXY: 1,
103+
REQUEST_URL: `http://badexample.com:${server.address().port}/test`,
104+
HTTP_PROXY: `http://localhost:${server.address().port}`,
105+
RESOLVE_TO_LOCALHOST: 'badexample.com',
106+
NO_PROXY: '.example.com',
107+
});
108+
109+
// The request should go through the proxy (not bypass it),
110+
// because badexample.com is not a subdomain of example.com.
111+
assert.match(stdout, /Status Code: 200/);
112+
assert.strictEqual(stderr.trim(), '');
113+
assert.strictEqual(code, 0);
114+
assert.strictEqual(signal, null);
115+
}
116+
80117
proxy.close();
81118
server.close();

0 commit comments

Comments
 (0)