Skip to content

Commit d1b28f7

Browse files
committed
dns: allow --dns-verbatim to change default dns verbatim
Allow the "--dns-verbatim" 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.
1 parent cbe3b27 commit d1b28f7

File tree

8 files changed

+165
-5
lines changed

8 files changed

+165
-5
lines changed

doc/api/cli.md

+13
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ Make built-in language features like `eval` and `new Function` that generate
181181
code from strings throw an exception instead. This does not affect the Node.js
182182
`vm` module.
183183

184+
### `--dns-verbatim=value`
185+
<!-- YAML
186+
added: REPLACEME
187+
-->
188+
189+
Set the default value of `verbatim` in [`dns.lookup()`][]. The value may be:
190+
* `0` to indicate `false`
191+
* `1` to indicate `true`
192+
193+
Other values will be ignored.
194+
184195
### `--enable-fips`
185196
<!-- YAML
186197
added: v6.0.0
@@ -1371,6 +1382,7 @@ Node.js options that are allowed are:
13711382
* `--conditions`
13721383
* `--diagnostic-dir`
13731384
* `--disable-proto`
1385+
* `--dns-verbatim`
13741386
* `--enable-fips`
13751387
* `--enable-source-maps`
13761388
* `--experimental-abortcontroller`
@@ -1728,6 +1740,7 @@ $ node --max-old-space-size=1536 index.js
17281740
[`NODE_OPTIONS`]: #cli_node_options_options
17291741
[`NO_COLOR`]: https://no-color.org
17301742
[`SlowBuffer`]: buffer.md#buffer_class_slowbuffer
1743+
[`dns.lookup()`]: dns.md#dns_dns_lookup_hostname_options_callback
17311744
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#process_process_setuncaughtexceptioncapturecallback_fn
17321745
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tls_tls_default_max_version
17331746
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tls_tls_default_min_version

lib/dns.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const {
4141
Resolver,
4242
validateHints,
4343
emitInvalidHostnameWarning,
44+
getDefaultVerbatim,
4445
} = require('internal/dns/utils');
4546
const {
4647
ERR_INVALID_ARG_TYPE,
@@ -96,7 +97,7 @@ function lookup(hostname, options, callback) {
9697
let hints = 0;
9798
let family = -1;
9899
let all = false;
99-
let verbatim = false;
100+
let verbatim = getDefaultVerbatim();
100101

101102
// Parse arguments
102103
if (hostname) {
@@ -113,7 +114,9 @@ function lookup(hostname, options, callback) {
113114
hints = options.hints >>> 0;
114115
family = options.family >>> 0;
115116
all = options.all === true;
116-
verbatim = options.verbatim === true;
117+
if (typeof options.verbatim === 'boolean') {
118+
verbatim = options.verbatim === true;
119+
}
117120

118121
validateHints(hints);
119122
} else {

lib/internal/dns/promises.js

+5-3
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 {

lib/internal/dns/utils.js

+22
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ 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,
@@ -184,6 +185,26 @@ function emitInvalidHostnameWarning(hostname) {
184185
);
185186
}
186187

188+
let defaultVerbatim = null;
189+
190+
function getDefaultVerbatim() {
191+
if (defaultVerbatim !== null) {
192+
return defaultVerbatim;
193+
}
194+
195+
const option = getOptionValue('--dns-verbatim');
196+
switch (option) {
197+
case '1':
198+
defaultVerbatim = true;
199+
break;
200+
case '0':
201+
default:
202+
defaultVerbatim = false;
203+
}
204+
205+
return defaultVerbatim;
206+
}
207+
187208
module.exports = {
188209
bindDefaultResolver,
189210
getDefaultResolver,
@@ -192,4 +213,5 @@ module.exports = {
192213
validateTimeout,
193214
Resolver,
194215
emitInvalidHostnameWarning,
216+
getDefaultVerbatim,
195217
};

src/node_options.cc

+5
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
297297
" (default: current working directory)",
298298
&EnvironmentOptions::diagnostic_dir,
299299
kAllowedInEnvironment);
300+
AddOption("--dns-verbatim",
301+
"set to 1 or 0 to enable or disable "
302+
"verbatim in dns.lookup by default",
303+
&EnvironmentOptions::dns_verbatim,
304+
kAllowedInEnvironment);
300305
AddOption("--enable-source-maps",
301306
"Source Map V3 support for stack traces",
302307
&EnvironmentOptions::enable_source_maps,

src/node_options.h

+1
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_verbatim;
104105
bool enable_source_maps = false;
105106
bool experimental_json_modules = false;
106107
bool experimental_modules = false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Flags: --expose-internals --dns-verbatim=0
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-verbatim=0 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+
34+
await allowFailed(promisify(dns.lookup)('example.org'));
35+
assert.strictEqual(calls.length, callsLength + 1);
36+
verbatim = calls[callsLength][4];
37+
assert.strictEqual(verbatim, false);
38+
callsLength += 1;
39+
40+
await allowFailed(dnsPromises.lookup('example.org'));
41+
assert.strictEqual(calls.length, callsLength + 1);
42+
verbatim = calls[callsLength][4];
43+
assert.strictEqual(verbatim, false);
44+
callsLength += 1;
45+
46+
await allowFailed(promisify(dns.lookup)('example.org', {}));
47+
assert.strictEqual(calls.length, callsLength + 1);
48+
verbatim = calls[callsLength][4];
49+
assert.strictEqual(verbatim, false);
50+
callsLength += 1;
51+
52+
await allowFailed(dnsPromises.lookup('example.org', {}));
53+
assert.strictEqual(calls.length, callsLength + 1);
54+
verbatim = calls[callsLength][4];
55+
assert.strictEqual(verbatim, false);
56+
callsLength += 1;
57+
})().then(common.mustCall());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Flags: --expose-internals --dns-verbatim=1
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-verbatim=1 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+
34+
await allowFailed(promisify(dns.lookup)('example.org'));
35+
assert.strictEqual(calls.length, callsLength + 1);
36+
verbatim = calls[callsLength][4];
37+
assert.strictEqual(verbatim, true);
38+
callsLength += 1;
39+
40+
await allowFailed(dnsPromises.lookup('example.org'));
41+
assert.strictEqual(calls.length, callsLength + 1);
42+
verbatim = calls[callsLength][4];
43+
assert.strictEqual(verbatim, true);
44+
callsLength += 1;
45+
46+
await allowFailed(promisify(dns.lookup)('example.org', {}));
47+
assert.strictEqual(calls.length, callsLength + 1);
48+
verbatim = calls[callsLength][4];
49+
assert.strictEqual(verbatim, true);
50+
callsLength += 1;
51+
52+
await allowFailed(dnsPromises.lookup('example.org', {}));
53+
assert.strictEqual(calls.length, callsLength + 1);
54+
verbatim = calls[callsLength][4];
55+
assert.strictEqual(verbatim, true);
56+
callsLength += 1;
57+
})().then(common.mustCall());

0 commit comments

Comments
 (0)