Skip to content

Commit

Permalink
dns: allow --dns-verbatim to change default dns verbatim
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
oyyd committed Apr 9, 2021
1 parent f96dffb commit 8564a8b
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 5 deletions.
13 changes: 13 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ Make built-in language features like `eval` and `new Function` that generate
code from strings throw an exception instead. This does not affect the Node.js
`vm` module.

### `--dns-verbatim=value`
<!-- YAML
added: REPLACEME
-->

Set the default value of `verbatim` in [`dns.lookup()`][]. The value may be:
* `0` to indicate `false`
* `1` to indicate `true`

Other values will be ignored.

### `--enable-fips`
<!-- YAML
added: v6.0.0
Expand Down Expand Up @@ -1371,6 +1382,7 @@ Node.js options that are allowed are:
* `--conditions`
* `--diagnostic-dir`
* `--disable-proto`
* `--dns-verbatim`
* `--enable-fips`
* `--enable-source-maps`
* `--experimental-abortcontroller`
Expand Down Expand Up @@ -1728,6 +1740,7 @@ $ node --max-old-space-size=1536 index.js
[`NODE_OPTIONS`]: #cli_node_options_options
[`NO_COLOR`]: https://no-color.org
[`SlowBuffer`]: buffer.md#buffer_class_slowbuffer
[`dns.lookup()`]: dns.md#dns_dns_lookup_hostname_options_callback
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#process_process_setuncaughtexceptioncapturecallback_fn
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tls_tls_default_max_version
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tls_tls_default_min_version
Expand Down
7 changes: 5 additions & 2 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const {
Resolver,
validateHints,
emitInvalidHostnameWarning,
getDefaultVerbatim,
} = require('internal/dns/utils');
const {
ERR_INVALID_ARG_TYPE,
Expand Down Expand Up @@ -96,7 +97,7 @@ function lookup(hostname, options, callback) {
let hints = 0;
let family = -1;
let all = false;
let verbatim = false;
let verbatim = getDefaultVerbatim();

// Parse arguments
if (hostname) {
Expand All @@ -113,7 +114,9 @@ function lookup(hostname, options, callback) {
hints = options.hints >>> 0;
family = options.family >>> 0;
all = options.all === true;
verbatim = options.verbatim === true;
if (typeof options.verbatim === 'boolean') {
verbatim = options.verbatim === true;
}

validateHints(hints);
} else {
Expand Down
8 changes: 5 additions & 3 deletions lib/internal/dns/promises.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
'use strict';

const {
ArrayPrototypeMap,
ObjectCreate,
Expand All @@ -14,6 +13,7 @@ const {
validateHints,
validateTimeout,
emitInvalidHostnameWarning,
getDefaultVerbatim,
} = require('internal/dns/utils');
const { codes, dnsException } = require('internal/errors');
const { toASCII } = require('internal/idna');
Expand Down Expand Up @@ -103,7 +103,7 @@ function lookup(hostname, options) {
var hints = 0;
var family = -1;
var all = false;
var verbatim = false;
var verbatim = getDefaultVerbatim();

// Parse arguments
if (hostname && typeof hostname !== 'string') {
Expand All @@ -112,7 +112,9 @@ function lookup(hostname, options) {
hints = options.hints >>> 0;
family = options.family >>> 0;
all = options.all === true;
verbatim = options.verbatim === true;
if (typeof options.verbatim === 'boolean') {
verbatim = options.verbatim === true;
}

validateHints(hints);
} else {
Expand Down
22 changes: 22 additions & 0 deletions lib/internal/dns/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {

const errors = require('internal/errors');
const { isIP } = require('internal/net');
const { getOptionValue } = require('internal/options');
const {
validateArray,
validateInt32,
Expand Down Expand Up @@ -184,6 +185,26 @@ function emitInvalidHostnameWarning(hostname) {
);
}

let defaultVerbatim = null;

function getDefaultVerbatim() {
if (defaultVerbatim !== null) {
return defaultVerbatim;
}

const option = getOptionValue('--dns-verbatim');
switch (option) {
case '1':
defaultVerbatim = true;
break;
case '0':
default:
defaultVerbatim = false;
}

return defaultVerbatim;
}

module.exports = {
bindDefaultResolver,
getDefaultResolver,
Expand All @@ -192,4 +213,5 @@ module.exports = {
validateTimeout,
Resolver,
emitInvalidHostnameWarning,
getDefaultVerbatim,
};
5 changes: 5 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
" (default: current working directory)",
&EnvironmentOptions::diagnostic_dir,
kAllowedInEnvironment);
AddOption("--dns-verbatim",
"set to 1 or 0 to enable or disable "
"verbatim in dns.lookup by default",
&EnvironmentOptions::dns_verbatim,
kAllowedInEnvironment);
AddOption("--enable-source-maps",
"Source Map V3 support for stack traces",
&EnvironmentOptions::enable_source_maps,
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class EnvironmentOptions : public Options {
public:
bool abort_on_uncaught_exception = false;
std::vector<std::string> conditions;
std::string dns_verbatim;
bool enable_source_maps = false;
bool experimental_json_modules = false;
bool experimental_modules = false;
Expand Down
57 changes: 57 additions & 0 deletions test/parallel/test-dns-default-verbatim-false.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Flags: --expose-internals --dns-verbatim=0
'use strict';
const common = require('../common');
const assert = require('assert');
const { internalBinding } = require('internal/test/binding');
const cares = internalBinding('cares_wrap');
const { promisify } = require('util');

// Test that --dns-verbatim=0 works as expected.

const originalGetaddrinfo = cares.getaddrinfo;
const calls = [];
cares.getaddrinfo = common.mustCallAtLeast((...args) => {
calls.push(args);
originalGetaddrinfo(...args);
}, 1);

const dns = require('dns');
const dnsPromises = dns.promises;

let verbatim;

// We want to test the parameter of verbatim only so that we
// ignore possible errors here.
function allowFailed(fn) {
return fn.catch((_err) => {
//
});
}

(async () => {
let callsLength = 0;

await allowFailed(promisify(dns.lookup)('example.org'));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, false);
callsLength += 1;

await allowFailed(dnsPromises.lookup('example.org'));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, false);
callsLength += 1;

await allowFailed(promisify(dns.lookup)('example.org', {}));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, false);
callsLength += 1;

await allowFailed(dnsPromises.lookup('example.org', {}));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, false);
callsLength += 1;
})().then(common.mustCall());
57 changes: 57 additions & 0 deletions test/parallel/test-dns-default-verbatim-true.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Flags: --expose-internals --dns-verbatim=1
'use strict';
const common = require('../common');
const assert = require('assert');
const { internalBinding } = require('internal/test/binding');
const cares = internalBinding('cares_wrap');
const { promisify } = require('util');

// Test that --dns-verbatim=1 works as expected.

const originalGetaddrinfo = cares.getaddrinfo;
const calls = [];
cares.getaddrinfo = common.mustCallAtLeast((...args) => {
calls.push(args);
originalGetaddrinfo(...args);
}, 1);

const dns = require('dns');
const dnsPromises = dns.promises;

let verbatim;

// We want to test the parameter of verbatim only so that we
// ignore possible errors here.
function allowFailed(fn) {
return fn.catch((_err) => {
//
});
}

(async () => {
let callsLength = 0;

await allowFailed(promisify(dns.lookup)('example.org'));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, true);
callsLength += 1;

await allowFailed(dnsPromises.lookup('example.org'));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, true);
callsLength += 1;

await allowFailed(promisify(dns.lookup)('example.org', {}));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, true);
callsLength += 1;

await allowFailed(dnsPromises.lookup('example.org', {}));
assert.strictEqual(calls.length, callsLength + 1);
verbatim = calls[callsLength][4];
assert.strictEqual(verbatim, true);
callsLength += 1;
})().then(common.mustCall());

0 comments on commit 8564a8b

Please sign in to comment.