Skip to content

Commit 633a990

Browse files
silverwindcjihrig
authored andcommitted
dns: allow dns.lookup() to return all addresses
This commit adds the 'all' option to dns.lookup(), allowing all lookup results to be returned. Semver: Minor Fixes: #736 PR-URL: #744 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 1cd1d7a commit 633a990

File tree

3 files changed

+148
-27
lines changed

3 files changed

+148
-27
lines changed

doc/api/dns.markdown

+22-14
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,37 @@ AAAA (IPv6) record. `options` can be an object or integer. If `options` is
6161
not provided, then IP v4 and v6 addresses are both valid. If `options` is
6262
an integer, then it must be `4` or `6`.
6363

64-
Alternatively, `options` can be an object containing two properties,
65-
`family` and `hints`. Both properties are optional. If `family` is provided,
66-
it must be the integer `4` or `6`. If `family` is not provided then IP v4
67-
and v6 addresses are accepted. The `hints` field, if present, should be one
68-
or more of the supported `getaddrinfo` flags. If `hints` is not provided,
69-
then no flags are passed to `getaddrinfo`. Multiple flags can be passed
70-
through `hints` by logically `OR`ing their values. An example usage of
71-
`options` is shown below.
64+
Alternatively, `options` can be an object containing these properties:
65+
66+
* `family` {Number} - The record family. If present, must be the integer
67+
`4` or `6`. If not provided, both IP v4 and v6 addresses are accepted.
68+
* `hints`: {Number} - If present, it should be one or more of the supported
69+
`getaddrinfo` flags. If `hints` is not provided, then no flags are passed to
70+
`getaddrinfo`. Multiple flags can be passed through `hints` by logically
71+
`OR`ing their values.
72+
See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below
73+
for more information on supported flags.
74+
* `all`: {Boolean} - When `true`, the callback returns all resolved addresses
75+
in an array, otherwise returns a single address. Defaults to `false`.
76+
77+
All properties are optional. An example usage of options is shown below.
7278

7379
```
7480
{
7581
family: 4,
7682
hints: dns.ADDRCONFIG | dns.V4MAPPED
83+
all: true
7784
}
7885
```
7986

80-
See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below for
81-
more information on supported flags.
87+
The callback has arguments `(err, address, family)`. `address` is a string
88+
representation of a IP v4 or v6 address. `family` is either the integer 4 or 6
89+
and denotes the family of `address` (not necessarily the value initially passed
90+
to `lookup`).
8291

83-
The callback has arguments `(err, address, family)`. The `address` argument
84-
is a string representation of a IP v4 or v6 address. The `family` argument
85-
is either the integer 4 or 6 and denotes the family of `address` (not
86-
necessarily the value initially passed to `lookup`).
92+
With the `all` option set, the arguments change to `(err, addresses)`, with
93+
`addresses` being an array of objects with the properties `address` and
94+
`family`.
8795

8896
On error, `err` is an `Error` object, where `err.code` is the error code.
8997
Keep in mind that `err.code` will be set to `'ENOENT'` not only when

lib/dns.js

+30-3
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,29 @@ function onlookup(err, addresses) {
8282
}
8383

8484

85+
function onlookupall(err, addresses) {
86+
var results = [];
87+
if (err) {
88+
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));
89+
}
90+
91+
for (var i = 0; i < addresses.length; i++) {
92+
results.push({
93+
address: addresses[i],
94+
family: this.family || (addresses[i].indexOf(':') >= 0 ? 6 : 4)
95+
});
96+
}
97+
98+
this.callback(null, results);
99+
}
100+
101+
85102
// Easy DNS A/AAAA look up
86103
// lookup(hostname, [options,] callback)
87104
exports.lookup = function lookup(hostname, options, callback) {
88105
var hints = 0;
89106
var family = -1;
107+
var all = false;
90108

91109
// Parse arguments
92110
if (hostname && typeof hostname !== 'string') {
@@ -99,6 +117,7 @@ exports.lookup = function lookup(hostname, options, callback) {
99117
} else if (options !== null && typeof options === 'object') {
100118
hints = options.hints >>> 0;
101119
family = options.family >>> 0;
120+
all = options.all === true;
102121

103122
if (hints !== 0 &&
104123
hints !== exports.ADDRCONFIG &&
@@ -121,21 +140,29 @@ exports.lookup = function lookup(hostname, options, callback) {
121140
callback = makeAsync(callback);
122141

123142
if (!hostname) {
124-
callback(null, null, family === 6 ? 6 : 4);
143+
if (all) {
144+
callback(null, []);
145+
} else {
146+
callback(null, null, family === 6 ? 6 : 4);
147+
}
125148
return {};
126149
}
127150

128151
var matchedFamily = net.isIP(hostname);
129152
if (matchedFamily) {
130-
callback(null, hostname, matchedFamily);
153+
if (all) {
154+
callback(null, [{address: hostname, family: matchedFamily}]);
155+
} else {
156+
callback(null, hostname, matchedFamily);
157+
}
131158
return {};
132159
}
133160

134161
var req = new GetAddrInfoReqWrap();
135162
req.callback = callback;
136163
req.family = family;
137164
req.hostname = hostname;
138-
req.oncomplete = onlookup;
165+
req.oncomplete = all ? onlookupall : onlookup;
139166

140167
var err = cares.getaddrinfo(req, hostname, family, hints);
141168
if (err) {

test/internet/test-dns.js

+96-10
Original file line numberDiff line numberDiff line change
@@ -226,34 +226,34 @@ TEST(function test_resolveNaptr(done) {
226226
TEST(function test_resolveSoa(done) {
227227
var req = dns.resolveSoa('nodejs.org', function(err, result) {
228228
if (err) throw err;
229-
229+
230230
assert.ok(result);
231231
assert.ok(typeof result === 'object');
232-
232+
233233
assert.ok(typeof result.nsname === 'string');
234234
assert.ok(result.nsname.length > 0);
235-
235+
236236
assert.ok(typeof result.hostmaster === 'string');
237237
assert.ok(result.hostmaster.length > 0);
238-
238+
239239
assert.ok(typeof result.serial === 'number');
240240
assert.ok((result.serial > 0) && (result.serial < 4294967295));
241-
241+
242242
assert.ok(typeof result.refresh === 'number');
243-
assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
244-
243+
assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
244+
245245
assert.ok(typeof result.retry === 'number');
246246
assert.ok((result.retry > 0) && (result.retry < 2147483647));
247-
247+
248248
assert.ok(typeof result.expire === 'number');
249249
assert.ok((result.expire > 0) && (result.expire < 2147483647));
250-
250+
251251
assert.ok(typeof result.minttl === 'number');
252252
assert.ok((result.minttl >= 0) && (result.minttl < 2147483647));
253253

254254
done();
255255
});
256-
256+
257257
checkWrap(req);
258258
});
259259

@@ -471,6 +471,92 @@ TEST(function test_lookup_localhost_ipv4(done) {
471471
});
472472

473473

474+
TEST(function test_lookup_ip_all(done) {
475+
var req = dns.lookup('127.0.0.1', {all: true}, function(err, ips, family) {
476+
if (err) throw err;
477+
assert.ok(Array.isArray(ips));
478+
assert.ok(ips.length > 0);
479+
assert.strictEqual(ips[0].address, '127.0.0.1');
480+
assert.strictEqual(ips[0].family, 4);
481+
482+
done();
483+
});
484+
485+
checkWrap(req);
486+
});
487+
488+
489+
TEST(function test_lookup_null_all(done) {
490+
var req = dns.lookup(null, {all: true}, function(err, ips, family) {
491+
if (err) throw err;
492+
assert.ok(Array.isArray(ips));
493+
assert.strictEqual(ips.length, 0);
494+
495+
done();
496+
});
497+
498+
checkWrap(req);
499+
});
500+
501+
502+
TEST(function test_lookup_all_ipv4(done) {
503+
var req = dns.lookup('www.google.com', {all: true, family: 4}, function(err, ips) {
504+
if (err) throw err;
505+
assert.ok(Array.isArray(ips));
506+
assert.ok(ips.length > 0);
507+
508+
ips.forEach(function(ip) {
509+
assert.ok(isIPv4(ip.address));
510+
assert.strictEqual(ip.family, 4);
511+
});
512+
513+
done();
514+
});
515+
516+
checkWrap(req);
517+
});
518+
519+
520+
TEST(function test_lookup_all_ipv6(done) {
521+
var req = dns.lookup('www.google.com', {all: true, family: 6}, function(err, ips) {
522+
if (err) throw err;
523+
assert.ok(Array.isArray(ips));
524+
assert.ok(ips.length > 0);
525+
526+
ips.forEach(function(ip) {
527+
assert.ok(isIPv6(ip.address));
528+
assert.strictEqual(ip.family, 6);
529+
});
530+
531+
done();
532+
});
533+
534+
checkWrap(req);
535+
});
536+
537+
538+
TEST(function test_lookup_all_mixed(done) {
539+
var req = dns.lookup('www.google.com', {all: true}, function(err, ips) {
540+
if (err) throw err;
541+
assert.ok(Array.isArray(ips));
542+
assert.ok(ips.length > 0);
543+
544+
ips.forEach(function(ip) {
545+
if (isIPv4(ip.address))
546+
assert.equal(ip.family, 4);
547+
else if (isIPv6(ip.address))
548+
assert.equal(ip.family, 6);
549+
else
550+
assert(false);
551+
});
552+
553+
done();
554+
});
555+
556+
checkWrap(req);
557+
});
558+
559+
474560
TEST(function test_lookupservice_ip_ipv4(done) {
475561
var req = dns.lookupService('127.0.0.1', 80, function(err, host, service) {
476562
if (err) throw err;

0 commit comments

Comments
 (0)