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 not provided, then IP v4 and v6 addresses are both valid. If `options` is
an integer, then it must be `4` or `6`. an integer, then it must be `4` or `6`.
Alternatively, `options` can be an object containing two properties, Alternatively, `options` can be an object containing these 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 * `family` {Number} - The record family. If present, must be the integer
and v6 addresses are accepted. The `hints` field, if present, should be one `4` or `6`. If not provided, both IP v4 and v6 addresses are accepted.
or more of the supported `getaddrinfo` flags. If `hints` is not provided, * `hints`: {Number} - If present, it should be one or more of the supported
then no flags are passed to `getaddrinfo`. Multiple flags can be passed `getaddrinfo` flags. If `hints` is not provided, then no flags are passed to
through `hints` by logically `OR`ing their values. An example usage of `getaddrinfo`. Multiple flags can be passed through `hints` by logically
`options` is shown below. `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, family: 4,
hints: dns.ADDRCONFIG | dns.V4MAPPED hints: dns.ADDRCONFIG | dns.V4MAPPED
all: true
} }
``` ```
See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below for The callback has arguments `(err, address, family)`. `address` is a string
more information on supported flags. 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 With the `all` option set, the arguments change to `(err, addresses)`, with
is a string representation of a IP v4 or v6 address. The `family` argument `addresses` being an array of objects with the properties `address` and
is either the integer 4 or 6 and denotes the family of `address` (not `family`.
necessarily the value initially passed to `lookup`).
On error, `err` is an `Error` object, where `err.code` is the error code. 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 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 // Easy DNS A/AAAA look up
// lookup(hostname, [options,] callback) // lookup(hostname, [options,] callback)
exports.lookup = function lookup(hostname, options, callback) { exports.lookup = function lookup(hostname, options, callback) {
var hints = 0; var hints = 0;
var family = -1; var family = -1;
var all = false;
// Parse arguments // Parse arguments
if (hostname && typeof hostname !== 'string') { if (hostname && typeof hostname !== 'string') {
@ -99,6 +117,7 @@ exports.lookup = function lookup(hostname, options, callback) {
} else if (options !== null && typeof options === 'object') { } else if (options !== null && typeof options === 'object') {
hints = options.hints >>> 0; hints = options.hints >>> 0;
family = options.family >>> 0; family = options.family >>> 0;
all = options.all === true;
if (hints !== 0 && if (hints !== 0 &&
hints !== exports.ADDRCONFIG && hints !== exports.ADDRCONFIG &&
@ -121,13 +140,21 @@ exports.lookup = function lookup(hostname, options, callback) {
callback = makeAsync(callback); callback = makeAsync(callback);
if (!hostname) { if (!hostname) {
if (all) {
callback(null, []);
} else {
callback(null, null, family === 6 ? 6 : 4); callback(null, null, family === 6 ? 6 : 4);
}
return {}; return {};
} }
var matchedFamily = net.isIP(hostname); var matchedFamily = net.isIP(hostname);
if (matchedFamily) { if (matchedFamily) {
if (all) {
callback(null, [{address: hostname, family: matchedFamily}]);
} else {
callback(null, hostname, matchedFamily); callback(null, hostname, matchedFamily);
}
return {}; return {};
} }
@ -135,7 +162,7 @@ exports.lookup = function lookup(hostname, options, callback) {
req.callback = callback; req.callback = callback;
req.family = family; req.family = family;
req.hostname = hostname; req.hostname = hostname;
req.oncomplete = onlookup; req.oncomplete = all ? onlookupall : onlookup;
var err = cares.getaddrinfo(req, hostname, family, hints); var err = cares.getaddrinfo(req, hostname, family, hints);
if (err) { 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) { TEST(function test_lookupservice_ip_ipv4(done) {
var req = dns.lookupService('127.0.0.1', 80, function(err, host, service) { var req = dns.lookupService('127.0.0.1', 80, function(err, host, service) {
if (err) throw err; if (err) throw err;

Loading…
Cancel
Save