dns: refactor default resolver · nodejs/node@0f232e9 · GitHub
Skip to content

Commit 0f232e9

Browse files
joyeecheungRafaelGSS
authored andcommitted
dns: refactor default resolver
This patch refactors the DNS default resolver code to make it easier to be included in a snapshot: - The code specific for the callback-based DNS resolver are not in a separate module to make the dependency clearer (it's not actually needed if the user only ever loads `dns/promises`) - The common part of the callback-based resolver and the promise- based resolver is now ResolverBase. The other two user-facing resolvers are now subclasses of ResolverBase. The default Resolver is constructed with just ResolverBase. This would be fine as the default resolver is never actually exposed to the user-land and it has been working using duck-typing anyway. - Move the construction of Resolver subclasses into a common method `createResolverClass()` to reduce code duplication. The two subclasses now also share the same base constructor. This would make it possible for them to also share code for snapshot support later. - `--dns-result-order` is now queried and refreshed during pre-execution. To avoid loading the cares_wrap binding unnecessarily the loading of the binding is also made lazy. PR-URL: #44541 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
1 parent 2d87b6f commit 0f232e9

7 files changed

Lines changed: 191 additions & 141 deletions

File tree

lib/dns.js

Lines changed: 4 additions & 93 deletions
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
'use strict';
2+
3+
const {
4+
ObjectDefineProperty,
5+
ReflectApply,
6+
ArrayPrototypeMap,
7+
Symbol
8+
} = primordials;
9+
10+
const { toASCII } = require('internal/idna');
11+
12+
const {
13+
codes: {
14+
ERR_INVALID_ARG_TYPE,
15+
ERR_INVALID_ARG_VALUE,
16+
},
17+
dnsException
18+
} = require('internal/errors');
19+
20+
const {
21+
createResolverClass,
22+
} = require('internal/dns/utils');
23+
24+
const {
25+
validateFunction,
26+
validateString,
27+
} = require('internal/validators');
28+
29+
const {
30+
QueryReqWrap,
31+
} = internalBinding('cares_wrap');
32+
33+
const {
34+
hasObserver,
35+
startPerf,
36+
stopPerf,
37+
} = require('internal/perf/observe');
38+
39+
const kPerfHooksDnsLookupResolveContext = Symbol('kPerfHooksDnsLookupResolveContext');
40+
41+
function onresolve(err, result, ttls) {
42+
if (ttls && this.ttl)
43+
result = ArrayPrototypeMap(
44+
result, (address, index) => ({ address, ttl: ttls[index] }));
45+
46+
if (err)
47+
this.callback(dnsException(err, this.bindingName, this.hostname));
48+
else {
49+
this.callback(null, result);
50+
if (this[kPerfHooksDnsLookupResolveContext] && hasObserver('dns')) {
51+
stopPerf(this, kPerfHooksDnsLookupResolveContext, { detail: { result } });
52+
}
53+
}
54+
}
55+
56+
function resolver(bindingName) {
57+
function query(name, /* options, */ callback) {
58+
let options;
59+
if (arguments.length > 2) {
60+
options = callback;
61+
callback = arguments[2];
62+
}
63+
64+
validateString(name, 'name');
65+
validateFunction(callback, 'callback');
66+
67+
const req = new QueryReqWrap();
68+
req.bindingName = bindingName;
69+
req.callback = callback;
70+
req.hostname = name;
71+
req.oncomplete = onresolve;
72+
req.ttl = !!(options && options.ttl);
73+
const err = this._handle[bindingName](req, toASCII(name));
74+
if (err) throw dnsException(err, bindingName, name);
75+
if (hasObserver('dns')) {
76+
startPerf(req, kPerfHooksDnsLookupResolveContext, {
77+
type: 'dns',
78+
name: bindingName,
79+
detail: {
80+
host: name,
81+
ttl: req.ttl,
82+
},
83+
});
84+
}
85+
return req;
86+
}
87+
ObjectDefineProperty(query, 'name', { __proto__: null, value: bindingName });
88+
return query;
89+
}
90+
91+
// This is the callback-based resolver. There is another similar
92+
// resolver in dns/promises.js with resolve methods that are based
93+
// on promises instead.
94+
const { Resolver, resolveMap } = createResolverClass(resolver);
95+
Resolver.prototype.resolve = resolve;
96+
97+
function resolve(hostname, rrtype, callback) {
98+
let resolver;
99+
if (typeof rrtype === 'string') {
100+
resolver = resolveMap[rrtype];
101+
} else if (typeof rrtype === 'function') {
102+
resolver = resolveMap.A;
103+
callback = rrtype;
104+
} else {
105+
throw new ERR_INVALID_ARG_TYPE('rrtype', 'string', rrtype);
106+
}
107+
108+
if (typeof resolver === 'function') {
109+
return ReflectApply(resolver, this, [hostname, callback]);
110+
}
111+
throw new ERR_INVALID_ARG_VALUE('rrtype', rrtype);
112+
}
113+
114+
module.exports = {
115+
Resolver
116+
};

lib/internal/dns/promises.js

Lines changed: 8 additions & 36 deletions

0 commit comments

Comments
 (0)