Skip to content

Commit

Permalink
fix: handle stream error to prevent uncaught DOMException and consume…
Browse files Browse the repository at this point in the history
… body if not used (per <nodejs/undici#3353>)
  • Loading branch information
titanism committed Aug 3, 2024
1 parent 20bcf27 commit 4035c48
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 30 deletions.
1 change: 1 addition & 0 deletions benchmarks/lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Tangerine = require('..');

const opts = { timeout: 5000, tries: 1 };

// eslint-disable-next-line n/prefer-promises/dns
dns.setServers(['1.1.1.1', '1.0.0.1']);

const resolver = new dns.promises.Resolver(opts);
Expand Down
1 change: 1 addition & 0 deletions benchmarks/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Tangerine = require('..');

const opts = { timeout: 5000, tries: 1 };

// eslint-disable-next-line n/prefer-promises/dns
dns.setServers(['1.1.1.1', '1.0.0.1']);

const resolver = new dns.promises.Resolver(opts);
Expand Down
1 change: 1 addition & 0 deletions benchmarks/reverse.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Tangerine = require('..');

const opts = { timeout: 5000, tries: 1 };

// eslint-disable-next-line n/prefer-promises/dns
dns.setServers(['1.1.1.1', '1.0.0.1']);

const resolver = new dns.promises.Resolver(opts);
Expand Down
34 changes: 30 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const autoBind = require('auto-bind');
const getStream = require('get-stream');
const hostile = require('hostile');
const ipaddr = require('ipaddr.js');
const isStream = require('is-stream');
const mergeOptions = require('merge-options');
const pMap = require('p-map');
const pTimeout = require('p-timeout');
Expand Down Expand Up @@ -702,8 +703,8 @@ class Tangerine extends dns.promises.Resolver {

// safeguard (matches c-ares)
if (lower === 'localhost' || lower === 'localhost.') {
if (!resolve4) resolve4 = ['127.0.0.1'];
if (!resolve6) resolve6 = ['::1'];
resolve4 ||= ['127.0.0.1'];
resolve6 ||= ['::1'];
}

if (isIPv4(name)) {
Expand Down Expand Up @@ -1128,22 +1129,41 @@ class Tangerine extends dns.promises.Resolver {
const statusCode = response.status || response.statusCode;
debug('response', { statusCode, headers });

// <https://github.com/nodejs/undici/issues/3353#issuecomment-2184635954>
// eslint-disable-next-line max-depth
if (body && isStream(body) && typeof body.on === 'function')
body.on('error', (err) => {
this.options.logger.error(err, { response });
});

// eslint-disable-next-line max-depth
if (body && statusCode >= 200 && statusCode < 300) {
// <https://sindresorhus.com/blog/goodbye-nodejs-buffer>
buffer = Buffer.isBuffer(body)
? body
: // eslint-disable-next-line no-await-in-loop
await getStream.buffer(body);
// <https://github.com/nodejs/undici/issues/3353>
// eslint-disable-next-line no-await-in-loop, max-depth
if (body && typeof body.dump === 'function') await body.dump();
// eslint-disable-next-line max-depth
if (!abortController.signal.aborted) abortController.abort();
break;
}

// <https://github.com/nodejs/undici/issues/3353>
// eslint-disable-next-line no-await-in-loop, max-depth
if (body && typeof body.dump === 'function') await body.dump();

// <https://github.com/nodejs/undici/blob/00dfd0bd41e73782452aecb728395f354585ca94/lib/core/errors.js#L47-L58>
const message =
http.STATUS_CODES[statusCode] ||
this.options.defaultHTTPErrorMessage;
const err = new Error(message);
err.body = body;
err.status = statusCode;
err.statusCode = statusCode;
err.headers = headers;
throw err;
}
} catch (err) {
Expand Down Expand Up @@ -1202,6 +1222,12 @@ class Tangerine extends dns.promises.Resolver {
// that one or more dns servers have persistent issues
if (errors.length > 0)
this.options.logger.error(this.constructor.combineErrors(errors));

//
// NOTE: dns-packet does not yet support Uint8Array
// (however undici does have body.arrayBuffer() method)
//
// https://github.com/mafintosh/dns-packet/issues/72
return packet.decode(buffer);
} catch (_err) {
if (!abortController.signal.aborted) abortController.abort();
Expand Down Expand Up @@ -1886,8 +1912,8 @@ class Tangerine extends dns.promises.Resolver {
Buffer.isBuffer(a.data)
? a.data.toString()
: Array.isArray(a.data)
? a.data.map((d) => (Buffer.isBuffer(d) ? d.toString() : d))
: a.data
? a.data.map((d) => (Buffer.isBuffer(d) ? d.toString() : d))
: a.data
];
});
}
Expand Down
45 changes: 23 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,49 +12,50 @@
"dependencies": {
"@ungap/structured-clone": "^1.2.0",
"auto-bind": "4",
"dns-packet": "^5.6.0",
"dns-packet": "^5.6.1",
"dohdec": "^5.0.3",
"get-stream": "6",
"hostile": "^1.3.3",
"ipaddr.js": "^2.0.1",
"hostile": "^1.4.0",
"ipaddr.js": "^2.2.0",
"is-stream": "2.0.1",
"merge-options": "3.0.4",
"p-map": "4",
"p-timeout": "4",
"p-wait-for": "3",
"port-numbers": "6.0.1",
"private-ip": "^3.0.0",
"punycode": "^2.3.0",
"semver": "^7.5.1"
"private-ip": "^3.0.2",
"punycode": "^2.3.1",
"semver": "^7.6.3"
},
"devDependencies": {
"@commitlint/cli": "^17.6.3",
"@commitlint/config-conventional": "^17.6.3",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"ava": "^5.2.0",
"axios": "^1.4.0",
"axios": "^1.7.3",
"benchmark": "^2.1.4",
"cross-env": "^7.0.3",
"eslint": "^8.34.0",
"eslint": "^9.8.0",
"eslint-config-xo-lass": "^2.0.1",
"fetch-mock": "^9.11.0",
"fetch-mock": "^10.1.1",
"fixpack": "^4.0.0",
"got": "11",
"husky": "^8.0.3",
"ioredis": "^5.3.2",
"ioredis-mock": "^8.7.0",
"husky": "^9.1.4",
"ioredis": "^5.4.1",
"ioredis-mock": "^8.9.0",
"is-ci": "^3.0.1",
"lint-staged": "^13.2.2",
"lint-staged": "^15.2.8",
"lodash": "^4.17.21",
"nock": "^13.3.1",
"nock": "^13.5.4",
"node-fetch": "2",
"nyc": "^15.1.0",
"phin": "^3.7.0",
"remark-cli": "^11.0.0",
"nyc": "^17.0.0",
"phin": "^3.7.1",
"remark-cli": "11.0.0",
"remark-preset-github": "^4.0.4",
"request": "^2.88.2",
"sort-keys": "4.2.0",
"superagent": "^8.0.9",
"undici": "^5.22.1",
"xo": "^0.54.2"
"superagent": "^9.0.2",
"undici": "^6.19.5",
"xo": "^0.58.0"
},
"engines": {
"node": ">=16"
Expand Down
8 changes: 4 additions & 4 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,13 @@ function compareResults(t, type, r1, r2) {
_.isError(r1)
? r1
: Array.isArray(r1) && r1.every((s) => _.isString(s))
? r1.sort()
: sortKeys(r1),
? r1.sort()
: sortKeys(r1),
_.isError(r2)
? r2
: Array.isArray(r2) && r2.every((s) => _.isString(s))
? r2.sort()
: sortKeys(r2)
? r2.sort()
: sortKeys(r2)
);
}
}
Expand Down

0 comments on commit 4035c48

Please sign in to comment.