From 86d24c879fb418fa5ab29f633c5bc7642c9e9a36 Mon Sep 17 00:00:00 2001 From: LiviaMedeiros Date: Sun, 17 May 2026 01:03:49 +0800 Subject: [PATCH] dns: return `localhost` IP directly Signed-off-by: LiviaMedeiros --- lib/dns.js | 15 +++++++++++++++ lib/internal/dns/promises.js | 10 ++++++++++ test/async-hooks/test-graph.shutdown.js | 2 -- test/async-hooks/test-graph.tls-write.js | 2 -- test/parallel/test-dns-perf_hooks.js | 8 ++++---- .../parallel/test-http2-goaway-delayed-request.js | 2 +- test/parallel/test-permission-net-dns.js | 4 ++-- test/report/test-report-exclude-network.js | 13 +------------ 8 files changed, 33 insertions(+), 23 deletions(-) diff --git a/lib/dns.js b/lib/dns.js index d651f5ea0a2685..f636df0f74cc78 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -213,6 +213,21 @@ function lookup(hostname, options, callback) { return {}; } + if (hostname === 'localhost') { + const local4 = { address: '127.0.0.1', family: 4 }; + const local6 = { address: '::1', family: 6 }; + + if (all) { + const addresses = family === 4 ? [ local4 ] : family === 6 ? [ local6 ] : + dnsOrder === 'ipv6first' ? [ local6, local4 ] : [ local4, local6 ]; + process.nextTick(callback, null, addresses); + } else { + const { address, family: localFamily } = family === 6 || dnsOrder === 'ipv6first' ? local6 : local4; + process.nextTick(callback, null, address, localFamily); + } + return {}; + } + const req = new GetAddrInfoReqWrap(); req.callback = callback; req.family = family; diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js index f7ee8fd25423ca..f1c033588f014b 100644 --- a/lib/internal/dns/promises.js +++ b/lib/internal/dns/promises.js @@ -147,6 +147,16 @@ function createLookupPromise(family, hostname, all, hints, dnsOrder) { return; } + if (hostname === 'localhost') { + const local4 = { address: '127.0.0.1', family: 4 }; + const local6 = { address: '::1', family: 6 }; + const addresses = family === 4 ? [ local4 ] : family === 6 ? [ local6 ] : + dnsOrder === 'ipv6first' ? [ local6, local4 ] : [ local4, local6 ]; + + resolve(all ? addresses : addresses[0]); + return; + } + const req = new GetAddrInfoReqWrap(); req.family = family; diff --git a/test/async-hooks/test-graph.shutdown.js b/test/async-hooks/test-graph.shutdown.js index 0f633787e5e59d..234adf94eb1c32 100644 --- a/test/async-hooks/test-graph.shutdown.js +++ b/test/async-hooks/test-graph.shutdown.js @@ -36,8 +36,6 @@ function onexit() { hooks, [ { type: 'TCPSERVERWRAP', id: 'tcpserver:1', triggerAsyncId: null }, { type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: 'tcpserver:1' }, - { type: 'GETADDRINFOREQWRAP', - id: 'getaddrinforeq:1', triggerAsyncId: 'tcp:1' }, { type: 'TCPCONNECTWRAP', id: 'tcpconnect:1', triggerAsyncId: 'tcp:1' }, { type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcpserver:1' }, diff --git a/test/async-hooks/test-graph.tls-write.js b/test/async-hooks/test-graph.tls-write.js index 243039e01d116f..993b9efe682d44 100644 --- a/test/async-hooks/test-graph.tls-write.js +++ b/test/async-hooks/test-graph.tls-write.js @@ -60,8 +60,6 @@ function onexit() { [ { type: 'TCPSERVERWRAP', id: 'tcpserver:1', triggerAsyncId: null }, { type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: 'tcpserver:1' }, { type: 'TLSWRAP', id: 'tls:1', triggerAsyncId: 'tcpserver:1' }, - { type: 'GETADDRINFOREQWRAP', - id: 'getaddrinforeq:1', triggerAsyncId: 'tls:1' }, { type: 'TCPCONNECTWRAP', id: 'tcpconnect:1', triggerAsyncId: 'tcp:1' }, { type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcpserver:1' }, diff --git a/test/parallel/test-dns-perf_hooks.js b/test/parallel/test-dns-perf_hooks.js index 694b2e77249e7d..6bc20c87831a55 100644 --- a/test/parallel/test-dns-perf_hooks.js +++ b/test/parallel/test-dns-perf_hooks.js @@ -20,13 +20,13 @@ function inc() { // If DNS resolution fails, skip it // https://github.com/nodejs/node/issues/44003 -dns.lookup('localhost', common.mustCall((err) => { !err && inc(); })); +dns.lookup('nodejs.org', common.mustCall((err) => { !err && inc(); })); dns.lookupService('127.0.0.1', 80, common.mustCall((err) => { !err && inc(); })); -dns.resolveAny('localhost', common.mustCall((err) => { !err && inc(); })); +dns.resolveAny('nodejs.org', common.mustCall((err) => { !err && inc(); })); -dns.promises.lookup('localhost').then(inc).catch(() => {}); +dns.promises.lookup('nodejs.org').then(inc).catch(() => {}); dns.promises.lookupService('127.0.0.1', 80).then(inc).catch(() => {}); -dns.promises.resolveAny('localhost').then(inc).catch(() => {}); +dns.promises.resolveAny('nodejs.org').then(inc).catch(() => {}); process.on('exit', () => { assert.strictEqual(entries.length, count); diff --git a/test/parallel/test-http2-goaway-delayed-request.js b/test/parallel/test-http2-goaway-delayed-request.js index f5c6b0c965a28b..677515d222ddef 100644 --- a/test/parallel/test-http2-goaway-delayed-request.js +++ b/test/parallel/test-http2-goaway-delayed-request.js @@ -18,5 +18,5 @@ server.listen(0, common.mustCall(() => { const stream = client.request(); stream.on('error', common.expectsError({ code: 'ERR_HTTP2_GOAWAY_SESSION' })); - setImmediate(() => client.close()); + client.close(); })); diff --git a/test/parallel/test-permission-net-dns.js b/test/parallel/test-permission-net-dns.js index 13eaecf9279606..46992cc32aaeb2 100644 --- a/test/parallel/test-permission-net-dns.js +++ b/test/parallel/test-permission-net-dns.js @@ -7,10 +7,10 @@ const dns = require('dns'); const { Resolver } = dns.promises; { - dns.lookup('localhost', common.mustCall((err) => { + dns.lookup('nodejs.org', common.mustCall((err) => { assert.strictEqual(err.code, 'ERR_ACCESS_DENIED'); })); - dns.promises.lookup('localhost').catch(common.mustCall((err) => { + dns.promises.lookup('nodejs.org').catch(common.mustCall((err) => { assert.strictEqual(err.code, 'ERR_ACCESS_DENIED'); })); } diff --git a/test/report/test-report-exclude-network.js b/test/report/test-report-exclude-network.js index 7d0eaa08997cb5..6e7a89e7b3b7da 100644 --- a/test/report/test-report-exclude-network.js +++ b/test/report/test-report-exclude-network.js @@ -64,19 +64,8 @@ describe('report exclude network option', () => { (ep[ip4 ? 'ip4' : 'ip6'] === (ip4 ? '127.0.0.1' : '::1')), )?.[local ? 'localEndpoint' : 'remoteEndpoint']; }; - try { - // The reverse DNS of 127.0.0.1 can be a lot of things other than localhost - // it could resolve to the server name for instance - assert.notStrictEqual(findHandle(true)?.host, '127.0.0.1'); - assert.notStrictEqual(findHandle(false)?.host, '127.0.0.1'); - if (ipv6Available) { - assert.notStrictEqual(findHandle(true, false)?.host, '::1'); - assert.notStrictEqual(findHandle(false, false)?.host, '::1'); - } - } catch (e) { - throw new Error(e?.message + ' in ' + JSON.stringify(tcp, null, 2), { cause: e }); - } + // Lookup for 'localhost' does not require DNS queries, hence not tested process.report.excludeNetwork = true; report = process.report.getReport();