Skip to content

Commit 4acca8e

Browse files
ShogunPandamarco-ippolito
authored andcommitted
dns: add order option and support ipv6first
PR-URL: #52492 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
1 parent b6cb74d commit 4acca8e

21 files changed

+403
-91
lines changed

doc/api/cli.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -588,16 +588,20 @@ added:
588588
- v16.4.0
589589
- v14.18.0
590590
changes:
591+
- version: REPLACEME
592+
pr-url: https://github.com/nodejs/node/pull/52492
593+
description: The `ipv6first` is supported now.
591594
- version: v17.0.0
592595
pr-url: https://github.com/nodejs/node/pull/39987
593596
description: Changed default value to `verbatim`.
594597
-->
595598

596-
Set the default value of `verbatim` in [`dns.lookup()`][] and
599+
Set the default value of `order` in [`dns.lookup()`][] and
597600
[`dnsPromises.lookup()`][]. The value could be:
598601

599-
* `ipv4first`: sets default `verbatim` `false`.
600-
* `verbatim`: sets default `verbatim` `true`.
602+
* `ipv4first`: sets default `order` to `ipv4first`.
603+
* `ipv6first`: sets default `order` to `ipv6first`.
604+
* `verbatim`: sets default `order` to `verbatim`.
601605

602606
The default is `verbatim` and [`dns.setDefaultResultOrder()`][] have higher
603607
priority than `--dns-result-order`.

doc/api/dns.md

+53-13
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ section if a custom port is used.
179179
<!-- YAML
180180
added: v0.1.90
181181
changes:
182+
- version: REPLACEME
183+
pr-url: https://github.com/nodejs/node/pull/52492
184+
description: The `verbatim` option is now deprecated in favor of the new `order` option.
182185
- version: v18.4.0
183186
pr-url: https://github.com/nodejs/node/pull/43054
184187
description: For compatibility with `node:net`, when passing an option
@@ -211,9 +214,18 @@ changes:
211214
flags may be passed by bitwise `OR`ing their values.
212215
* `all` {boolean} When `true`, the callback returns all resolved addresses in
213216
an array. Otherwise, returns a single address. **Default:** `false`.
217+
* `order` {string} When `verbatim`, the resolved addresses are return
218+
unsorted. When `ipv4first`, the resolved addresses are sorted by placing
219+
IPv4 addresses before IPv6 addresses. When `ipv6first`, the resolved
220+
addresses are sorted by placing IPv6 addresses before IPv4 addresses.
221+
**Default:** `verbatim` (addresses are not reordered).
222+
Default value is configurable using [`dns.setDefaultResultOrder()`][] or
223+
[`--dns-result-order`][].
214224
* `verbatim` {boolean} When `true`, the callback receives IPv4 and IPv6
215225
addresses in the order the DNS resolver returned them. When `false`,
216226
IPv4 addresses are placed before IPv6 addresses.
227+
This option will be deprecated in favor of `order`. When both are specified,
228+
`order` has higher precedence. New code should only use `order`.
217229
**Default:** `true` (addresses are not reordered). Default value is
218230
configurable using [`dns.setDefaultResultOrder()`][] or
219231
[`--dns-result-order`][].
@@ -775,18 +787,22 @@ added:
775787
- v16.4.0
776788
- v14.18.0
777789
changes:
790+
- version: REPLACEME
791+
pr-url: https://github.com/nodejs/node/pull/52492
792+
description: The `ipv6first` value is supported now.
778793
- version: v17.0.0
779794
pr-url: https://github.com/nodejs/node/pull/39987
780795
description: Changed default value to `verbatim`.
781796
-->
782797

783-
* `order` {string} must be `'ipv4first'` or `'verbatim'`.
798+
* `order` {string} must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.
784799

785-
Set the default value of `verbatim` in [`dns.lookup()`][] and
800+
Set the default value of `order` in [`dns.lookup()`][] and
786801
[`dnsPromises.lookup()`][]. The value could be:
787802

788-
* `ipv4first`: sets default `verbatim` `false`.
789-
* `verbatim`: sets default `verbatim` `true`.
803+
* `ipv4first`: sets default `order` to `ipv4first`.
804+
* `ipv6first`: sets default `order` to `ipv6first`.
805+
* `verbatim`: sets default `order` to `verbatim`.
790806

791807
The default is `verbatim` and [`dns.setDefaultResultOrder()`][] have higher
792808
priority than [`--dns-result-order`][]. When using [worker threads][],
@@ -796,14 +812,21 @@ dns orders in workers.
796812
## `dns.getDefaultResultOrder()`
797813

798814
<!-- YAML
799-
added: v20.1.0
815+
added:
816+
- v20.1.0
817+
- v18.17.0
818+
changes:
819+
- version: REPLACEME
820+
pr-url: https://github.com/nodejs/node/pull/52492
821+
description: The `ipv6first` value is supported now.
800822
-->
801823

802-
Get the default value for `verbatim` in [`dns.lookup()`][] and
824+
Get the default value for `order` in [`dns.lookup()`][] and
803825
[`dnsPromises.lookup()`][]. The value could be:
804826

805-
* `ipv4first`: for `verbatim` defaulting to `false`.
806-
* `verbatim`: for `verbatim` defaulting to `true`.
827+
* `ipv4first`: for `order` defaulting to `ipv4first`.
828+
* `ipv6first`: for `order` defaulting to `ipv6first`.
829+
* `verbatim`: for `order` defaulting to `verbatim`.
807830

808831
## `dns.setServers(servers)`
809832

@@ -947,6 +970,10 @@ section if a custom port is used.
947970

948971
<!-- YAML
949972
added: v10.6.0
973+
changes:
974+
- version: REPLACEME
975+
pr-url: https://github.com/nodejs/node/pull/52492
976+
description: The `verbatim` option is now deprecated in favor of the new `order` option.
950977
-->
951978

952979
* `hostname` {string}
@@ -959,13 +986,22 @@ added: v10.6.0
959986
flags may be passed by bitwise `OR`ing their values.
960987
* `all` {boolean} When `true`, the `Promise` is resolved with all addresses in
961988
an array. Otherwise, returns a single address. **Default:** `false`.
989+
* `order` {string} When `verbatim`, the `Promise` is resolved with IPv4 and
990+
IPv6 addresses in the order the DNS resolver returned them. When `ipv4first`,
991+
IPv4 addresses are placed before IPv6 addresses. When `ipv6first`,
992+
IPv6 addresses are placed before IPv4 addresses.
993+
**Default:** `verbatim` (addresses are not reordered).
994+
Default value is configurable using [`dns.setDefaultResultOrder()`][] or
995+
[`--dns-result-order`][]. New code should use `{ order: 'verbatim' }`.
962996
* `verbatim` {boolean} When `true`, the `Promise` is resolved with IPv4 and
963997
IPv6 addresses in the order the DNS resolver returned them. When `false`,
964998
IPv4 addresses are placed before IPv6 addresses.
999+
This option will be deprecated in favor of `order`. When both are specified,
1000+
`order` has higher precedence. New code should only use `order`.
9651001
**Default:** currently `false` (addresses are reordered) but this is
9661002
expected to change in the not too distant future. Default value is
9671003
configurable using [`dns.setDefaultResultOrder()`][] or
968-
[`--dns-result-order`][]. New code should use `{ verbatim: true }`.
1004+
[`--dns-result-order`][].
9691005

9701006
Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or
9711007
AAAA (IPv6) record. All `option` properties are optional. If `options` is an
@@ -1347,18 +1383,22 @@ added:
13471383
- v16.4.0
13481384
- v14.18.0
13491385
changes:
1386+
- version: REPLACEME
1387+
pr-url: https://github.com/nodejs/node/pull/52492
1388+
description: The `ipv6first` value is supported now.
13501389
- version: v17.0.0
13511390
pr-url: https://github.com/nodejs/node/pull/39987
13521391
description: Changed default value to `verbatim`.
13531392
-->
13541393

1355-
* `order` {string} must be `'ipv4first'` or `'verbatim'`.
1394+
* `order` {string} must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.
13561395

1357-
Set the default value of `verbatim` in [`dns.lookup()`][] and
1396+
Set the default value of `order` in [`dns.lookup()`][] and
13581397
[`dnsPromises.lookup()`][]. The value could be:
13591398

1360-
* `ipv4first`: sets default `verbatim` `false`.
1361-
* `verbatim`: sets default `verbatim` `true`.
1399+
* `ipv4first`: sets default `order` to `ipv4first`.
1400+
* `ipv6first`: sets default `order` to `ipv6first`.
1401+
* `verbatim`: sets default `order` to `verbatim`.
13621402

13631403
The default is `verbatim` and [`dnsPromises.setDefaultResultOrder()`][] have
13641404
higher priority than [`--dns-result-order`][]. When using [worker threads][],

lib/dns.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ const {
4343
setDefaultResolver,
4444
validateHints,
4545
emitInvalidHostnameWarning,
46-
getDefaultVerbatim,
4746
getDefaultResultOrder,
4847
setDefaultResultOrder,
4948
errorCodes: dnsErrorCodes,
@@ -89,6 +88,9 @@ const {
8988
const {
9089
GetAddrInfoReqWrap,
9190
GetNameInfoReqWrap,
91+
DNS_ORDER_VERBATIM,
92+
DNS_ORDER_IPV4_FIRST,
93+
DNS_ORDER_IPV6_FIRST,
9294
} = cares;
9395

9496
const kPerfHooksDnsLookupContext = Symbol('kPerfHooksDnsLookupContext');
@@ -141,7 +143,7 @@ function lookup(hostname, options, callback) {
141143
let hints = 0;
142144
let family = 0;
143145
let all = false;
144-
let verbatim = getDefaultVerbatim();
146+
let dnsOrder = getDefaultResultOrder();
145147

146148
// Parse arguments
147149
if (hostname) {
@@ -187,7 +189,11 @@ function lookup(hostname, options, callback) {
187189
}
188190
if (options?.verbatim != null) {
189191
validateBoolean(options.verbatim, 'options.verbatim');
190-
verbatim = options.verbatim;
192+
dnsOrder = options.verbatim ? 'verbatim' : 'ipv4first';
193+
}
194+
if (options?.order != null) {
195+
validateOneOf(options.order, 'options.order', ['ipv4first', 'ipv6first', 'verbatim']);
196+
dnsOrder = options.dnsOrder;
191197
}
192198
}
193199

@@ -218,8 +224,16 @@ function lookup(hostname, options, callback) {
218224
req.hostname = hostname;
219225
req.oncomplete = all ? onlookupall : onlookup;
220226

227+
let order = DNS_ORDER_VERBATIM;
228+
229+
if (dnsOrder === 'ipv4first') {
230+
order = DNS_ORDER_IPV4_FIRST;
231+
} else if (dnsOrder === 'ipv6first') {
232+
order = DNS_ORDER_IPV6_FIRST;
233+
}
234+
221235
const err = cares.getaddrinfo(
222-
req, hostname, family, hints, verbatim,
236+
req, hostname, family, hints, order,
223237
);
224238
if (err) {
225239
process.nextTick(callback, new DNSException(err, 'getaddrinfo', hostname));
@@ -230,8 +244,10 @@ function lookup(hostname, options, callback) {
230244
hostname,
231245
family,
232246
hints,
233-
verbatim,
247+
verbatim: order === DNS_ORDER_VERBATIM,
248+
order: dnsOrder,
234249
};
250+
235251
startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail });
236252
}
237253
return req;

lib/internal/dns/promises.js

+26-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const {
1212
createResolverClass,
1313
validateHints,
1414
emitInvalidHostnameWarning,
15-
getDefaultVerbatim,
1615
errorCodes: dnsErrorCodes,
1716
getDefaultResultOrder,
1817
setDefaultResultOrder,
@@ -53,6 +52,9 @@ const {
5352
GetAddrInfoReqWrap,
5453
GetNameInfoReqWrap,
5554
QueryReqWrap,
55+
DNS_ORDER_VERBATIM,
56+
DNS_ORDER_IPV4_FIRST,
57+
DNS_ORDER_IPV6_FIRST,
5658
} = internalBinding('cares_wrap');
5759
const {
5860
ERR_INVALID_ARG_TYPE,
@@ -120,13 +122,13 @@ function onlookupall(err, addresses) {
120122
* @param {boolean} all - Whether to resolve with all IP addresses for the hostname.
121123
* @param {number} hints - One or more supported getaddrinfo flags (supply multiple via
122124
* bitwise OR).
123-
* @param {boolean} verbatim - Whether to use the hostname verbatim.
125+
* @param {number} dnsOrder - How to sort results. Must be `ipv4first`, `ipv6first` or `verbatim`.
124126
* @returns {Promise<DNSLookupResult | DNSLookupResult[]>} The IP address(es) of the hostname.
125127
* @typedef {object} DNSLookupResult
126128
* @property {string} address - The IP address.
127129
* @property {0 | 4 | 6} family - The IP address type. 4 for IPv4 or 6 for IPv6, or 0 (for both).
128130
*/
129-
function createLookupPromise(family, hostname, all, hints, verbatim) {
131+
function createLookupPromise(family, hostname, all, hints, dnsOrder) {
130132
return new Promise((resolve, reject) => {
131133
if (!hostname) {
132134
emitInvalidHostnameWarning(hostname);
@@ -150,7 +152,15 @@ function createLookupPromise(family, hostname, all, hints, verbatim) {
150152
req.resolve = resolve;
151153
req.reject = reject;
152154

153-
const err = getaddrinfo(req, hostname, family, hints, verbatim);
155+
let order = DNS_ORDER_VERBATIM;
156+
157+
if (dnsOrder === 'ipv4first') {
158+
order = DNS_ORDER_IPV4_FIRST;
159+
} else if (dnsOrder === 'ipv6first') {
160+
order = DNS_ORDER_IPV6_FIRST;
161+
}
162+
163+
const err = getaddrinfo(req, hostname, family, hints, order);
154164

155165
if (err) {
156166
reject(new DNSException(err, 'getaddrinfo', hostname));
@@ -159,7 +169,8 @@ function createLookupPromise(family, hostname, all, hints, verbatim) {
159169
hostname,
160170
family,
161171
hints,
162-
verbatim,
172+
verbatim: order === DNS_ORDER_VERBATIM,
173+
order: dnsOrder,
163174
};
164175
startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail });
165176
}
@@ -175,14 +186,15 @@ const validFamilies = [0, 4, 6];
175186
* @param {0 | 4 | 6} [options.family=0] - The record family. Must be 4, 6, or 0 (for both).
176187
* @param {number} [options.hints] - One or more supported getaddrinfo flags (supply multiple via
177188
* bitwise OR).
178-
* @param {boolean} [options.verbatim=false] - Return results in same order DNS resolved them;
179-
* otherwise IPv4 then IPv6. New code should supply `true`.
189+
* @param {string} [options.order='verbatim'] - Return results in same order DNS resolved them;
190+
* Must be `ipv4first`, `ipv6first` or `verbatim`.
191+
* New code should supply `verbatim`.
180192
*/
181193
function lookup(hostname, options) {
182194
let hints = 0;
183195
let family = 0;
184196
let all = false;
185-
let verbatim = getDefaultVerbatim();
197+
let dnsOrder = getDefaultResultOrder();
186198

187199
// Parse arguments
188200
if (hostname) {
@@ -210,11 +222,15 @@ function lookup(hostname, options) {
210222
}
211223
if (options?.verbatim != null) {
212224
validateBoolean(options.verbatim, 'options.verbatim');
213-
verbatim = options.verbatim;
225+
dnsOrder = options.verbatim ? 'verbatim' : 'ipv4first';
226+
}
227+
if (options?.order != null) {
228+
validateOneOf(options.order, 'options.order', ['ipv4first', 'ipv6first', 'verbatim']);
229+
dnsOrder = options.order;
214230
}
215231
}
216232

217-
return createLookupPromise(family, hostname, all, hints, verbatim);
233+
return createLookupPromise(family, hostname, all, hints, dnsOrder);
218234
}
219235

220236

lib/internal/dns/utils.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ function initializeDns() {
207207
dnsOrder ??= 'verbatim';
208208
} else {
209209
// Allow the deserialized application to override order from CLI.
210+
validateOneOf(orderFromCLI, '--dns-result-order', ['verbatim', 'ipv4first', 'ipv6first']);
210211
dnsOrder = orderFromCLI;
211212
}
212213

@@ -277,12 +278,8 @@ function emitInvalidHostnameWarning(hostname) {
277278
}
278279
}
279280

280-
function getDefaultVerbatim() {
281-
return dnsOrder !== 'ipv4first';
282-
}
283-
284281
function setDefaultResultOrder(value) {
285-
validateOneOf(value, 'dnsOrder', ['verbatim', 'ipv4first']);
282+
validateOneOf(value, 'dnsOrder', ['verbatim', 'ipv4first', 'ipv6first']);
286283
dnsOrder = value;
287284
}
288285

@@ -351,7 +348,6 @@ module.exports = {
351348
validateTimeout,
352349
validateTries,
353350
emitInvalidHostnameWarning,
354-
getDefaultVerbatim,
355351
getDefaultResultOrder,
356352
setDefaultResultOrder,
357353
errorCodes,

lib/internal/modules/esm/fetch_module.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ async function isLocalAddress(hostname) {
253253
) {
254254
hostname = StringPrototypeSlice(hostname, 1, -1);
255255
}
256-
const addr = await dnsLookup(hostname, { verbatim: true });
256+
const addr = await dnsLookup(hostname, { order: 'verbatim' });
257257
const ipv = addr.family === 4 ? 'ipv4' : 'ipv6';
258258
return allowList.check(addr.address, ipv);
259259
} catch {

0 commit comments

Comments
 (0)