Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a71df76

Browse filesBrowse files
oyydtargos
authored andcommitted
dns: allow --dns-result-order to change default dns verbatim
Allow the `--dns-result-order` option to change the default value of verbatim in `dns.lookup()`. This is useful when running Node.js in ipv6-only environments to avoid possible ENETUNREACH errors. PR-URL: #38099 Refs: #31566 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 84c3990 commit a71df76
Copy full SHA for a71df76

File tree

Expand file treeCollapse file tree

10 files changed

+298
-9
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

10 files changed

+298
-9
lines changed
Open diff view settings
Collapse file

‎doc/api/cli.md‎

Copy file name to clipboardExpand all lines: doc/api/cli.md
+17Lines changed: 17 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ Make built-in language features like `eval` and `new Function` that generate
187187
code from strings throw an exception instead. This does not affect the Node.js
188188
`vm` module.
189189

190+
### `--dns-result-order=order`
191+
<!-- YAML
192+
added: REPLACEME
193+
-->
194+
195+
Set the default value of `verbatim` in [`dns.lookup()`][] and
196+
[`dnsPromises.lookup()`][]. The value could be:
197+
* `ipv4first`: sets default `verbatim` `false`.
198+
* `verbatim`: sets default `verbatim` `true`.
199+
200+
The default is `ipv4first` and [`dns.setDefaultResultOrder()`][] have higher
201+
priority than `--dns-result-order`.
202+
190203
### `--enable-fips`
191204
<!-- YAML
192205
added: v6.0.0
@@ -1377,6 +1390,7 @@ Node.js options that are allowed are:
13771390
* `--conditions`, `-C`
13781391
* `--diagnostic-dir`
13791392
* `--disable-proto`
1393+
* `--dns-result-order`
13801394
* `--enable-fips`
13811395
* `--enable-source-maps`
13821396
* `--experimental-abortcontroller`
@@ -1765,6 +1779,9 @@ $ node --max-old-space-size=1536 index.js
17651779
[`NODE_OPTIONS`]: #cli_node_options_options
17661780
[`NO_COLOR`]: https://no-color.org
17671781
[`SlowBuffer`]: buffer.md#buffer_class_slowbuffer
1782+
[`dns.lookup()`]: dns.md#dns_dns_lookup_hostname_options_callback
1783+
[`dns.setDefaultResultOrder()`]: dns.md#dns_dns_setdefaultresultorder_order
1784+
[`dnsPromises.lookup()`]: dns.md#dns_dnspromises_lookup_hostname_options
17681785
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#process_process_setuncaughtexceptioncapturecallback_fn
17691786
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tls_tls_default_max_version
17701787
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tls_tls_default_min_version
Collapse file

‎doc/api/dns.md‎

Copy file name to clipboardExpand all lines: doc/api/dns.md
+44-4Lines changed: 44 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,9 @@ changes:
184184
addresses in the order the DNS resolver returned them. When `false`,
185185
IPv4 addresses are placed before IPv6 addresses.
186186
**Default:** currently `false` (addresses are reordered) but this is
187-
expected to change in the not too distant future.
188-
New code should use `{ verbatim: true }`.
187+
expected to change in the not too distant future. Default value is
188+
configurable using [`dns.setDefaultResultOrder()`][] or
189+
[`--dns-result-order`][]. New code should use `{ verbatim: true }`.
189190
* `callback` {Function}
190191
* `err` {Error}
191192
* `address` {string} A string representation of an IPv4 or IPv6 address.
@@ -629,6 +630,23 @@ array of host names.
629630
On error, `err` is an [`Error`][] object, where `err.code` is
630631
one of the [DNS error codes][].
631632

633+
## `dns.setDefaultResultOrder(order)`
634+
<!-- YAML
635+
added: REPLACEME
636+
-->
637+
638+
* `order` {string} must be `'ipv4first'` or `'verbatim'`.
639+
640+
Set the default value of `verbatim` in [`dns.lookup()`][] and
641+
[`dnsPromises.lookup()`][]. The value could be:
642+
* `ipv4first`: sets default `verbatim` `false`.
643+
* `verbatim`: sets default `verbatim` `true`.
644+
645+
The default is `ipv4first` and [`dns.setDefaultResultOrder()`][] have higher
646+
priority than [`--dns-result-order`][]. When using [worker threads][],
647+
[`dns.setDefaultResultOrder()`][] from the main thread won't affect the default
648+
dns orders in workers.
649+
632650
## `dns.setServers(servers)`
633651
<!-- YAML
634652
added: v0.11.3
@@ -777,8 +795,9 @@ added: v10.6.0
777795
IPv6 addresses in the order the DNS resolver returned them. When `false`,
778796
IPv4 addresses are placed before IPv6 addresses.
779797
**Default:** currently `false` (addresses are reordered) but this is
780-
expected to change in the not too distant future.
781-
New code should use `{ verbatim: true }`.
798+
expected to change in the not too distant future. Default value is
799+
configurable using [`dns.setDefaultResultOrder()`][] or
800+
[`--dns-result-order`][]. New code should use `{ verbatim: true }`.
782801

783802
Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or
784803
AAAA (IPv6) record. All `option` properties are optional. If `options` is an
@@ -1132,6 +1151,23 @@ array of host names.
11321151
On error, the `Promise` is rejected with an [`Error`][] object, where `err.code`
11331152
is one of the [DNS error codes](#dns_error_codes).
11341153

1154+
### `dnsPromises.setDefaultResultOrder(order)`
1155+
<!-- YAML
1156+
added: REPLACEME
1157+
-->
1158+
1159+
* `order` {string} must be `'ipv4first'` or `'verbatim'`.
1160+
1161+
Set the default value of `verbatim` in [`dns.lookup()`][] and
1162+
[`dnsPromises.lookup()`][]. The value could be:
1163+
* `ipv4first`: sets default `verbatim` `false`.
1164+
* `verbatim`: sets default `verbatim` `true`.
1165+
1166+
The default is `ipv4first` and [`dnsPromises.setDefaultResultOrder()`][] have
1167+
higher priority than [`--dns-result-order`][]. When using [worker threads][],
1168+
[`dnsPromises.setDefaultResultOrder()`][] from the main thread won't affect the
1169+
default dns orders in workers.
1170+
11351171
### `dnsPromises.setServers(servers)`
11361172
<!-- YAML
11371173
added: v10.6.0
@@ -1241,6 +1277,7 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
12411277
[Implementation considerations section]: #dns_implementation_considerations
12421278
[RFC 5952]: https://tools.ietf.org/html/rfc5952#section-6
12431279
[RFC 8482]: https://tools.ietf.org/html/rfc8482
1280+
[`--dns-result-order`]: cli.md#cli_dns_result_order_order
12441281
[`Error`]: errors.md#errors_class_error
12451282
[`UV_THREADPOOL_SIZE`]: cli.md#cli_uv_threadpool_size_size
12461283
[`dgram.createSocket()`]: dgram.md#dgram_dgram_createsocket_options_callback
@@ -1260,6 +1297,7 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
12601297
[`dns.resolveSrv()`]: #dns_dns_resolvesrv_hostname_callback
12611298
[`dns.resolveTxt()`]: #dns_dns_resolvetxt_hostname_callback
12621299
[`dns.reverse()`]: #dns_dns_reverse_ip_callback
1300+
[`dns.setDefaultResultOrder()`]: #dns_dns_setdefaultresultorder_order
12631301
[`dns.setServers()`]: #dns_dns_setservers_servers
12641302
[`dnsPromises.getServers()`]: #dns_dnspromises_getservers
12651303
[`dnsPromises.lookup()`]: #dns_dnspromises_lookup_hostname_options
@@ -1277,7 +1315,9 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
12771315
[`dnsPromises.resolveSrv()`]: #dns_dnspromises_resolvesrv_hostname
12781316
[`dnsPromises.resolveTxt()`]: #dns_dnspromises_resolvetxt_hostname
12791317
[`dnsPromises.reverse()`]: #dns_dnspromises_reverse_ip
1318+
[`dnsPromises.setDefaultResultOrder()`]: #dns_dnspromises_setdefaultresultorder_order
12801319
[`dnsPromises.setServers()`]: #dns_dnspromises_setservers_servers
12811320
[`socket.connect()`]: net.md#net_socket_connect_options_connectlistener
12821321
[`util.promisify()`]: util.md#util_util_promisify_original
12831322
[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags
1323+
[worker threads]: worker_threads.md
Collapse file

‎lib/dns.js‎

Copy file name to clipboardExpand all lines: lib/dns.js
+8-2Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const {
4141
Resolver,
4242
validateHints,
4343
emitInvalidHostnameWarning,
44+
getDefaultVerbatim,
45+
setDefaultResultOrder,
4446
} = require('internal/dns/utils');
4547
const {
4648
ERR_INVALID_ARG_TYPE,
@@ -96,7 +98,7 @@ function lookup(hostname, options, callback) {
9698
let hints = 0;
9799
let family = -1;
98100
let all = false;
99-
let verbatim = false;
101+
let verbatim = getDefaultVerbatim();
100102

101103
// Parse arguments
102104
if (hostname) {
@@ -113,7 +115,9 @@ function lookup(hostname, options, callback) {
113115
hints = options.hints >>> 0;
114116
family = options.family >>> 0;
115117
all = options.all === true;
116-
verbatim = options.verbatim === true;
118+
if (typeof options.verbatim === 'boolean') {
119+
verbatim = options.verbatim === true;
120+
}
117121

118122
validateHints(hints);
119123
} else {
@@ -286,6 +290,7 @@ module.exports = {
286290
lookupService,
287291

288292
Resolver,
293+
setDefaultResultOrder,
289294
setServers: defaultResolverSetServers,
290295

291296
// uv_getaddrinfo flags
@@ -330,6 +335,7 @@ ObjectDefineProperties(module.exports, {
330335
if (promises === null) {
331336
promises = require('internal/dns/promises');
332337
promises.setServers = defaultResolverSetServers;
338+
promises.setDefaultResultOrder = setDefaultResultOrder;
333339
}
334340
return promises;
335341
}
Collapse file

‎lib/internal/dns/promises.js‎

Copy file name to clipboardExpand all lines: lib/internal/dns/promises.js
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
'use strict';
2-
32
const {
43
ArrayPrototypeMap,
54
ObjectCreate,
@@ -14,6 +13,7 @@ const {
1413
validateHints,
1514
validateTimeout,
1615
emitInvalidHostnameWarning,
16+
getDefaultVerbatim,
1717
} = require('internal/dns/utils');
1818
const { codes, dnsException } = require('internal/errors');
1919
const { toASCII } = require('internal/idna');
@@ -103,7 +103,7 @@ function lookup(hostname, options) {
103103
var hints = 0;
104104
var family = -1;
105105
var all = false;
106-
var verbatim = false;
106+
var verbatim = getDefaultVerbatim();
107107

108108
// Parse arguments
109109
if (hostname && typeof hostname !== 'string') {
@@ -112,7 +112,9 @@ function lookup(hostname, options) {
112112
hints = options.hints >>> 0;
113113
family = options.family >>> 0;
114114
all = options.all === true;
115-
verbatim = options.verbatim === true;
115+
if (typeof options.verbatim === 'boolean') {
116+
verbatim = options.verbatim === true;
117+
}
116118

117119
validateHints(hints);
118120
} else {
Collapse file

‎lib/internal/dns/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/dns/utils.js
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ const {
1313

1414
const errors = require('internal/errors');
1515
const { isIP } = require('internal/net');
16+
const { getOptionValue } = require('internal/options');
1617
const {
1718
validateArray,
1819
validateInt32,
20+
validateOneOf,
1921
validateString,
2022
} = require('internal/validators');
2123
const {
@@ -184,6 +186,23 @@ function emitInvalidHostnameWarning(hostname) {
184186
);
185187
}
186188

189+
let dnsOrder = getOptionValue('--dns-result-order') || 'ipv4first';
190+
191+
function getDefaultVerbatim() {
192+
switch (dnsOrder) {
193+
case 'verbatim':
194+
return true;
195+
case 'ipv4first':
196+
default:
197+
return false;
198+
}
199+
}
200+
201+
function setDefaultResultOrder(value) {
202+
validateOneOf(value, 'dnsOrder', ['verbatim', 'ipv4first']);
203+
dnsOrder = value;
204+
}
205+
187206
module.exports = {
188207
bindDefaultResolver,
189208
getDefaultResolver,
@@ -192,4 +211,6 @@ module.exports = {
192211
validateTimeout,
193212
Resolver,
194213
emitInvalidHostnameWarning,
214+
getDefaultVerbatim,
215+
setDefaultResultOrder,
195216
};
Collapse file

‎src/node_options.cc‎

Copy file name to clipboardExpand all lines: src/node_options.cc
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,13 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
298298
" (default: current working directory)",
299299
&EnvironmentOptions::diagnostic_dir,
300300
kAllowedInEnvironment);
301+
AddOption("--dns-result-order",
302+
"set default value of verbatim in dns.lookup. Options are "
303+
"'ipv4first' (IPv4 addresses are placed before IPv6 addresses) "
304+
"'verbatim' (addresses are in the order the DNS resolver "
305+
"returned)",
306+
&EnvironmentOptions::dns_result_order,
307+
kAllowedInEnvironment);
301308
AddOption("--enable-source-maps",
302309
"Source Map V3 support for stack traces",
303310
&EnvironmentOptions::enable_source_maps,
Collapse file

‎src/node_options.h‎

Copy file name to clipboardExpand all lines: src/node_options.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class EnvironmentOptions : public Options {
101101
public:
102102
bool abort_on_uncaught_exception = false;
103103
std::vector<std::string> conditions;
104+
std::string dns_result_order;
104105
bool enable_source_maps = false;
105106
bool experimental_json_modules = false;
106107
bool experimental_modules = false;
Collapse file
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Flags: --expose-internals --dns-result-order=ipv4first
2+
'use strict';
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const { internalBinding } = require('internal/test/binding');
6+
const cares = internalBinding('cares_wrap');
7+
const { promisify } = require('util');
8+
9+
// Test that --dns-result-order=ipv4first works as expected.
10+
11+
const originalGetaddrinfo = cares.getaddrinfo;
12+
const calls = [];
13+
cares.getaddrinfo = common.mustCallAtLeast((...args) => {
14+
calls.push(args);
15+
originalGetaddrinfo(...args);
16+
}, 1);
17+
18+
const dns = require('dns');
19+
const dnsPromises = dns.promises;
20+
21+
let verbatim;
22+
23+
// We want to test the parameter of verbatim only so that we
24+
// ignore possible errors here.
25+
function allowFailed(fn) {
26+
return fn.catch((_err) => {
27+
//
28+
});
29+
}
30+
31+
(async () => {
32+
let callsLength = 0;
33+
const checkParameter = (expected) => {
34+
assert.strictEqual(calls.length, callsLength + 1);
35+
verbatim = calls[callsLength][4];
36+
assert.strictEqual(verbatim, expected);
37+
callsLength += 1;
38+
};
39+
40+
await allowFailed(promisify(dns.lookup)('example.org'));
41+
checkParameter(false);
42+
43+
await allowFailed(dnsPromises.lookup('example.org'));
44+
checkParameter(false);
45+
46+
await allowFailed(promisify(dns.lookup)('example.org', {}));
47+
checkParameter(false);
48+
49+
await allowFailed(dnsPromises.lookup('example.org', {}));
50+
checkParameter(false);
51+
})().then(common.mustCall());
Collapse file
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Flags: --expose-internals --dns-result-order=verbatim
2+
'use strict';
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const { internalBinding } = require('internal/test/binding');
6+
const cares = internalBinding('cares_wrap');
7+
const { promisify } = require('util');
8+
9+
// Test that --dns-result-order=verbatim works as expected.
10+
11+
const originalGetaddrinfo = cares.getaddrinfo;
12+
const calls = [];
13+
cares.getaddrinfo = common.mustCallAtLeast((...args) => {
14+
calls.push(args);
15+
originalGetaddrinfo(...args);
16+
}, 1);
17+
18+
const dns = require('dns');
19+
const dnsPromises = dns.promises;
20+
21+
let verbatim;
22+
23+
// We want to test the parameter of verbatim only so that we
24+
// ignore possible errors here.
25+
function allowFailed(fn) {
26+
return fn.catch((_err) => {
27+
//
28+
});
29+
}
30+
31+
(async () => {
32+
let callsLength = 0;
33+
const checkParameter = (expected) => {
34+
assert.strictEqual(calls.length, callsLength + 1);
35+
verbatim = calls[callsLength][4];
36+
assert.strictEqual(verbatim, expected);
37+
callsLength += 1;
38+
};
39+
40+
await allowFailed(promisify(dns.lookup)('example.org'));
41+
checkParameter(true);
42+
43+
await allowFailed(dnsPromises.lookup('example.org'));
44+
checkParameter(true);
45+
46+
await allowFailed(promisify(dns.lookup)('example.org', {}));
47+
checkParameter(true);
48+
49+
await allowFailed(dnsPromises.lookup('example.org', {}));
50+
checkParameter(true);
51+
})().then(common.mustCall());

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.