dns: implement {ttl: true} for dns.resolve4()
Add an option to retrieve the Time-To-Live of the A record. PR-URL: https://github.com/nodejs/node/pull/9296 Refs: https://github.com/nodejs/node/issues/5893 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io>
This commit is contained in:
parent
b80f05efaa
commit
c31b507b94
@ -183,7 +183,7 @@ corresponding lookup methods.
|
|||||||
On error, `err` is an [`Error`][] object, where `err.code` is
|
On error, `err` is an [`Error`][] object, where `err.code` is
|
||||||
one of the error codes listed [here](#dns_error_codes).
|
one of the error codes listed [here](#dns_error_codes).
|
||||||
|
|
||||||
## dns.resolve4(hostname, callback)
|
## dns.resolve4(hostname[, options], callback)
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.16
|
added: v0.1.16
|
||||||
-->
|
-->
|
||||||
@ -193,6 +193,13 @@ Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the
|
|||||||
will contain an array of IPv4 addresses (e.g.
|
will contain an array of IPv4 addresses (e.g.
|
||||||
`['74.125.79.104', '74.125.79.105', '74.125.79.106']`).
|
`['74.125.79.104', '74.125.79.105', '74.125.79.106']`).
|
||||||
|
|
||||||
|
* `hostname` {String} Hostname to resolve.
|
||||||
|
* `options` {Object}
|
||||||
|
* `ttl` {Boolean} Retrieve the Time-To-Live value (TTL) of each record.
|
||||||
|
The callback receives an array of `{ address: '1.2.3.4', ttl: 60 }` objects
|
||||||
|
rather than an array of strings. The TTL is expressed in seconds.
|
||||||
|
* `callback` {Function} An `(err, result)` callback function.
|
||||||
|
|
||||||
## dns.resolve6(hostname, callback)
|
## dns.resolve6(hostname, callback)
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.16
|
added: v0.1.16
|
||||||
|
14
lib/dns.js
14
lib/dns.js
@ -211,7 +211,10 @@ exports.lookupService = function lookupService(host, port, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function onresolve(err, result) {
|
function onresolve(err, result, ttls) {
|
||||||
|
if (ttls && this.ttl)
|
||||||
|
result = result.map((address, index) => ({ address, ttl: ttls[index] }));
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
this.callback(errnoException(err, this.bindingName, this.hostname));
|
this.callback(errnoException(err, this.bindingName, this.hostname));
|
||||||
else
|
else
|
||||||
@ -222,7 +225,13 @@ function onresolve(err, result) {
|
|||||||
function resolver(bindingName) {
|
function resolver(bindingName) {
|
||||||
var binding = cares[bindingName];
|
var binding = cares[bindingName];
|
||||||
|
|
||||||
return function query(name, callback) {
|
return function query(name, /* options, */ callback) {
|
||||||
|
var options;
|
||||||
|
if (arguments.length > 2) {
|
||||||
|
options = callback;
|
||||||
|
callback = arguments[2];
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof name !== 'string') {
|
if (typeof name !== 'string') {
|
||||||
throw new Error('"name" argument must be a string');
|
throw new Error('"name" argument must be a string');
|
||||||
} else if (typeof callback !== 'function') {
|
} else if (typeof callback !== 'function') {
|
||||||
@ -235,6 +244,7 @@ function resolver(bindingName) {
|
|||||||
req.callback = callback;
|
req.callback = callback;
|
||||||
req.hostname = name;
|
req.hostname = name;
|
||||||
req.oncomplete = onresolve;
|
req.oncomplete = onresolve;
|
||||||
|
req.ttl = !!(options && options.ttl);
|
||||||
var err = binding(req, name);
|
var err = binding(req, name);
|
||||||
if (err) throw errnoException(err, bindingName);
|
if (err) throw errnoException(err, bindingName);
|
||||||
callback.immediately = true;
|
callback.immediately = true;
|
||||||
|
@ -336,25 +336,17 @@ class QueryWrap : public AsyncWrap {
|
|||||||
delete wrap;
|
delete wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallOnComplete(Local<Value> answer) {
|
void CallOnComplete(Local<Value> answer,
|
||||||
HandleScope handle_scope(env()->isolate());
|
Local<Value> extra = Local<Value>()) {
|
||||||
Context::Scope context_scope(env()->context());
|
|
||||||
Local<Value> argv[] = {
|
|
||||||
Integer::New(env()->isolate(), 0),
|
|
||||||
answer
|
|
||||||
};
|
|
||||||
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallOnComplete(Local<Value> answer, Local<Value> family) {
|
|
||||||
HandleScope handle_scope(env()->isolate());
|
HandleScope handle_scope(env()->isolate());
|
||||||
Context::Scope context_scope(env()->context());
|
Context::Scope context_scope(env()->context());
|
||||||
Local<Value> argv[] = {
|
Local<Value> argv[] = {
|
||||||
Integer::New(env()->isolate(), 0),
|
Integer::New(env()->isolate(), 0),
|
||||||
answer,
|
answer,
|
||||||
family
|
extra
|
||||||
};
|
};
|
||||||
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
|
const int argc = arraysize(argv) - extra.IsEmpty();
|
||||||
|
MakeCallback(env()->oncomplete_string(), argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseError(int status) {
|
void ParseError(int status) {
|
||||||
@ -400,18 +392,27 @@ class QueryAWrap: public QueryWrap {
|
|||||||
HandleScope handle_scope(env()->isolate());
|
HandleScope handle_scope(env()->isolate());
|
||||||
Context::Scope context_scope(env()->context());
|
Context::Scope context_scope(env()->context());
|
||||||
|
|
||||||
struct hostent* host;
|
hostent* host;
|
||||||
|
ares_addrttl addrttls[256];
|
||||||
|
int naddrttls = arraysize(addrttls);
|
||||||
|
|
||||||
int status = ares_parse_a_reply(buf, len, &host, nullptr, nullptr);
|
int status = ares_parse_a_reply(buf, len, &host, addrttls, &naddrttls);
|
||||||
if (status != ARES_SUCCESS) {
|
if (status != ARES_SUCCESS) {
|
||||||
ParseError(status);
|
ParseError(status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<Array> addresses = HostentToAddresses(env(), host);
|
Local<Array> addresses = HostentToAddresses(env(), host);
|
||||||
|
Local<Array> ttls = Array::New(env()->isolate(), naddrttls);
|
||||||
|
|
||||||
|
auto context = env()->context();
|
||||||
|
for (int i = 0; i < naddrttls; i += 1) {
|
||||||
|
auto value = Integer::New(env()->isolate(), addrttls[i].ttl);
|
||||||
|
ttls->Set(context, i, value).FromJust();
|
||||||
|
}
|
||||||
ares_free_hostent(host);
|
ares_free_hostent(host);
|
||||||
|
|
||||||
this->CallOnComplete(addresses);
|
CallOnComplete(addresses, ttls);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,6 +60,26 @@ TEST(function test_reverse_bogus(done) {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
TEST(function test_resolve4_ttl(done) {
|
||||||
|
var req = dns.resolve4('google.com', { ttl: true }, function(err, result) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.ok(result.length > 0);
|
||||||
|
|
||||||
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
var item = result[i];
|
||||||
|
assert.ok(item);
|
||||||
|
assert.strictEqual(typeof item, 'object');
|
||||||
|
assert.strictEqual(typeof item.ttl, 'number');
|
||||||
|
assert.strictEqual(typeof item.address, 'string');
|
||||||
|
assert.ok(item.ttl > 0);
|
||||||
|
assert.ok(isIPv4(item.address));
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
checkWrap(req);
|
||||||
|
});
|
||||||
|
|
||||||
TEST(function test_resolveMx(done) {
|
TEST(function test_resolveMx(done) {
|
||||||
var req = dns.resolveMx('gmail.com', function(err, result) {
|
var req = dns.resolveMx('gmail.com', function(err, result) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user