Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dns - add 'all' option to dns.lookup #744

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions doc/api/dns.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 30 additions & 3 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand All @@ -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 &&
Expand All @@ -121,21 +140,29 @@ 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 {};
}

var req = new GetAddrInfoReqWrap();
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) {
Expand Down
106 changes: 96 additions & 10 deletions test/internet/test-dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand Down Expand Up @@ -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;
Expand Down