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: https://github.com/iojs/io.js/issues/736 PR-URL: https://github.com/iojs/io.js/pull/744 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
1cd1d7a182
commit
633a990848
@ -61,29 +61,37 @@ AAAA (IPv6) record. `options` can be an object or integer. If `options` is
|
||||
not provided, then IP v4 and v6 addresses are both valid. If `options` is
|
||||
an integer, then it must be `4` or `6`.
|
||||
|
||||
Alternatively, `options` can be an object containing two properties,
|
||||
`family` and `hints`. Both properties are optional. If `family` is provided,
|
||||
it must be the integer `4` or `6`. If `family` is not provided then IP v4
|
||||
and v6 addresses are accepted. The `hints` field, if present, should be one
|
||||
or more of the supported `getaddrinfo` flags. If `hints` is not provided,
|
||||
then no flags are passed to `getaddrinfo`. Multiple flags can be passed
|
||||
through `hints` by logically `OR`ing their values. An example usage of
|
||||
`options` is shown below.
|
||||
Alternatively, `options` can be an object containing these properties:
|
||||
|
||||
* `family` {Number} - The record family. If present, must be the integer
|
||||
`4` or `6`. If not provided, both IP v4 and v6 addresses are accepted.
|
||||
* `hints`: {Number} - If present, it should be one or more of the supported
|
||||
`getaddrinfo` flags. If `hints` is not provided, then no flags are passed to
|
||||
`getaddrinfo`. Multiple flags can be passed through `hints` by logically
|
||||
`OR`ing their values.
|
||||
See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below
|
||||
for more information on supported flags.
|
||||
* `all`: {Boolean} - When `true`, the callback returns all resolved addresses
|
||||
in an array, otherwise returns a single address. Defaults to `false`.
|
||||
|
||||
All properties are optional. An example usage of options is shown below.
|
||||
|
||||
```
|
||||
{
|
||||
family: 4,
|
||||
hints: dns.ADDRCONFIG | dns.V4MAPPED
|
||||
all: true
|
||||
}
|
||||
```
|
||||
|
||||
See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below for
|
||||
more information on supported flags.
|
||||
The callback has arguments `(err, address, family)`. `address` is a string
|
||||
representation of a IP v4 or v6 address. `family` is either the integer 4 or 6
|
||||
and denotes the family of `address` (not necessarily the value initially passed
|
||||
to `lookup`).
|
||||
|
||||
The callback has arguments `(err, address, family)`. The `address` argument
|
||||
is a string representation of a IP v4 or v6 address. The `family` argument
|
||||
is either the integer 4 or 6 and denotes the family of `address` (not
|
||||
necessarily the value initially passed to `lookup`).
|
||||
With the `all` option set, the arguments change to `(err, addresses)`, with
|
||||
`addresses` being an array of objects with the properties `address` and
|
||||
`family`.
|
||||
|
||||
On error, `err` is an `Error` object, where `err.code` is the error code.
|
||||
Keep in mind that `err.code` will be set to `'ENOENT'` not only when
|
||||
|
33
lib/dns.js
33
lib/dns.js
@ -82,11 +82,29 @@ function onlookup(err, addresses) {
|
||||
}
|
||||
|
||||
|
||||
function onlookupall(err, addresses) {
|
||||
var results = [];
|
||||
if (err) {
|
||||
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));
|
||||
}
|
||||
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
results.push({
|
||||
address: addresses[i],
|
||||
family: this.family || (addresses[i].indexOf(':') >= 0 ? 6 : 4)
|
||||
});
|
||||
}
|
||||
|
||||
this.callback(null, results);
|
||||
}
|
||||
|
||||
|
||||
// Easy DNS A/AAAA look up
|
||||
// lookup(hostname, [options,] callback)
|
||||
exports.lookup = function lookup(hostname, options, callback) {
|
||||
var hints = 0;
|
||||
var family = -1;
|
||||
var all = false;
|
||||
|
||||
// Parse arguments
|
||||
if (hostname && typeof hostname !== 'string') {
|
||||
@ -99,6 +117,7 @@ exports.lookup = function lookup(hostname, options, callback) {
|
||||
} else if (options !== null && typeof options === 'object') {
|
||||
hints = options.hints >>> 0;
|
||||
family = options.family >>> 0;
|
||||
all = options.all === true;
|
||||
|
||||
if (hints !== 0 &&
|
||||
hints !== exports.ADDRCONFIG &&
|
||||
@ -121,13 +140,21 @@ exports.lookup = function lookup(hostname, options, callback) {
|
||||
callback = makeAsync(callback);
|
||||
|
||||
if (!hostname) {
|
||||
callback(null, null, family === 6 ? 6 : 4);
|
||||
if (all) {
|
||||
callback(null, []);
|
||||
} else {
|
||||
callback(null, null, family === 6 ? 6 : 4);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
var matchedFamily = net.isIP(hostname);
|
||||
if (matchedFamily) {
|
||||
callback(null, hostname, matchedFamily);
|
||||
if (all) {
|
||||
callback(null, [{address: hostname, family: matchedFamily}]);
|
||||
} else {
|
||||
callback(null, hostname, matchedFamily);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -135,7 +162,7 @@ exports.lookup = function lookup(hostname, options, callback) {
|
||||
req.callback = callback;
|
||||
req.family = family;
|
||||
req.hostname = hostname;
|
||||
req.oncomplete = onlookup;
|
||||
req.oncomplete = all ? onlookupall : onlookup;
|
||||
|
||||
var err = cares.getaddrinfo(req, hostname, family, hints);
|
||||
if (err) {
|
||||
|
@ -226,34 +226,34 @@ TEST(function test_resolveNaptr(done) {
|
||||
TEST(function test_resolveSoa(done) {
|
||||
var req = dns.resolveSoa('nodejs.org', function(err, result) {
|
||||
if (err) throw err;
|
||||
|
||||
|
||||
assert.ok(result);
|
||||
assert.ok(typeof result === 'object');
|
||||
|
||||
|
||||
assert.ok(typeof result.nsname === 'string');
|
||||
assert.ok(result.nsname.length > 0);
|
||||
|
||||
|
||||
assert.ok(typeof result.hostmaster === 'string');
|
||||
assert.ok(result.hostmaster.length > 0);
|
||||
|
||||
|
||||
assert.ok(typeof result.serial === 'number');
|
||||
assert.ok((result.serial > 0) && (result.serial < 4294967295));
|
||||
|
||||
|
||||
assert.ok(typeof result.refresh === 'number');
|
||||
assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
|
||||
|
||||
assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
|
||||
|
||||
assert.ok(typeof result.retry === 'number');
|
||||
assert.ok((result.retry > 0) && (result.retry < 2147483647));
|
||||
|
||||
|
||||
assert.ok(typeof result.expire === 'number');
|
||||
assert.ok((result.expire > 0) && (result.expire < 2147483647));
|
||||
|
||||
|
||||
assert.ok(typeof result.minttl === 'number');
|
||||
assert.ok((result.minttl >= 0) && (result.minttl < 2147483647));
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
@ -471,6 +471,92 @@ TEST(function test_lookup_localhost_ipv4(done) {
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_ip_all(done) {
|
||||
var req = dns.lookup('127.0.0.1', {all: true}, function(err, ips, family) {
|
||||
if (err) throw err;
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
assert.strictEqual(ips[0].address, '127.0.0.1');
|
||||
assert.strictEqual(ips[0].family, 4);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_null_all(done) {
|
||||
var req = dns.lookup(null, {all: true}, function(err, ips, family) {
|
||||
if (err) throw err;
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.strictEqual(ips.length, 0);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_all_ipv4(done) {
|
||||
var req = dns.lookup('www.google.com', {all: true, family: 4}, function(err, ips) {
|
||||
if (err) throw err;
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
ips.forEach(function(ip) {
|
||||
assert.ok(isIPv4(ip.address));
|
||||
assert.strictEqual(ip.family, 4);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_all_ipv6(done) {
|
||||
var req = dns.lookup('www.google.com', {all: true, family: 6}, function(err, ips) {
|
||||
if (err) throw err;
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
ips.forEach(function(ip) {
|
||||
assert.ok(isIPv6(ip.address));
|
||||
assert.strictEqual(ip.family, 6);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_all_mixed(done) {
|
||||
var req = dns.lookup('www.google.com', {all: true}, function(err, ips) {
|
||||
if (err) throw err;
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
ips.forEach(function(ip) {
|
||||
if (isIPv4(ip.address))
|
||||
assert.equal(ip.family, 4);
|
||||
else if (isIPv6(ip.address))
|
||||
assert.equal(ip.family, 6);
|
||||
else
|
||||
assert(false);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookupservice_ip_ipv4(done) {
|
||||
var req = dns.lookupService('127.0.0.1', 80, function(err, host, service) {
|
||||
if (err) throw err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user