Browse Source

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>
v1.8.0-commit
Roman Reiss 10 years ago
committed by cjihrig
parent
commit
633a990848
  1. 36
      doc/api/dns.markdown
  2. 29
      lib/dns.js
  3. 86
      test/internet/test-dns.js

36
doc/api/dns.markdown

@ -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

29
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) {
if (all) {
callback(null, []);
} else {
callback(null, null, family === 6 ? 6 : 4);
}
return {};
}
var matchedFamily = net.isIP(hostname);
if (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) {

86
test/internet/test-dns.js

@ -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…
Cancel
Save