dns: add promisified dns module
PR-URL: https://github.com/nodejs/node/pull/21264 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
parent
fea3595c2f
commit
7486c4d710
466
doc/api/dns.md
466
doc/api/dns.md
@ -568,6 +568,456 @@ An error will be thrown if an invalid address is provided.
|
||||
The `dns.setServers()` method must not be called while a DNS query is in
|
||||
progress.
|
||||
|
||||
## DNS Promises API
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
The `dns.promises` API provides an alternative set of asynchronous DNS methods
|
||||
that return `Promise` objects rather than using callbacks. The API is accessible
|
||||
via `require('dns').promises`.
|
||||
|
||||
### Class: dnsPromises.Resolver
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
An independent resolver for DNS requests.
|
||||
|
||||
Note that creating a new resolver uses the default server settings. Setting
|
||||
the servers used for a resolver using
|
||||
[`resolver.setServers()`][`dnsPromises.setServers()`] does not affect
|
||||
other resolvers:
|
||||
|
||||
```js
|
||||
const { Resolver } = require('dns').promises;
|
||||
const resolver = new Resolver();
|
||||
resolver.setServers(['4.4.4.4']);
|
||||
|
||||
// This request will use the server at 4.4.4.4, independent of global settings.
|
||||
resolver.resolve4('example.org').then((addresses) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
// Alternatively, the same code can be written using async-await style.
|
||||
(async function() {
|
||||
const addresses = await resolver.resolve4('example.org');
|
||||
})();
|
||||
```
|
||||
|
||||
The following methods from the `dnsPromises` API are available:
|
||||
|
||||
* [`resolver.getServers()`][`dnsPromises.getServers()`]
|
||||
* [`resolver.setServers()`][`dnsPromises.setServers()`]
|
||||
* [`resolver.resolve()`][`dnsPromises.resolve()`]
|
||||
* [`resolver.resolve4()`][`dnsPromises.resolve4()`]
|
||||
* [`resolver.resolve6()`][`dnsPromises.resolve6()`]
|
||||
* [`resolver.resolveAny()`][`dnsPromises.resolveAny()`]
|
||||
* [`resolver.resolveCname()`][`dnsPromises.resolveCname()`]
|
||||
* [`resolver.resolveMx()`][`dnsPromises.resolveMx()`]
|
||||
* [`resolver.resolveNaptr()`][`dnsPromises.resolveNaptr()`]
|
||||
* [`resolver.resolveNs()`][`dnsPromises.resolveNs()`]
|
||||
* [`resolver.resolvePtr()`][`dnsPromises.resolvePtr()`]
|
||||
* [`resolver.resolveSoa()`][`dnsPromises.resolveSoa()`]
|
||||
* [`resolver.resolveSrv()`][`dnsPromises.resolveSrv()`]
|
||||
* [`resolver.resolveTxt()`][`dnsPromises.resolveTxt()`]
|
||||
* [`resolver.reverse()`][`dnsPromises.reverse()`]
|
||||
|
||||
#### resolver.cancel()
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
Cancel all outstanding DNS queries made by this resolver. The corresponding
|
||||
`Promise`s will be rejected with an error with code `ECANCELLED`.
|
||||
|
||||
### dnsPromises.getServers()
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* Returns: {string[]}
|
||||
|
||||
Returns an array of IP address strings, formatted according to [rfc5952][],
|
||||
that are currently configured for DNS resolution. A string will include a port
|
||||
section if a custom port is used.
|
||||
|
||||
<!-- eslint-disable semi-->
|
||||
```js
|
||||
[
|
||||
'4.4.4.4',
|
||||
'2001:4860:4860::8888',
|
||||
'4.4.4.4:1053',
|
||||
'[2001:4860:4860::8888]:1053'
|
||||
]
|
||||
```
|
||||
|
||||
### dnsPromises.lookup(hostname[, options])
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
- `options` {integer | Object}
|
||||
- `family` {integer} The record family. Must be `4` or `6`. IPv4
|
||||
and IPv6 addresses are both returned by default.
|
||||
- `hints` {number} One or more [supported `getaddrinfo` flags][]. Multiple
|
||||
flags may be passed by bitwise `OR`ing their values.
|
||||
- `all` {boolean} When `true`, the `Promise` is resolved with all addresses in
|
||||
an array. Otherwise, returns a single address. **Default:** `false`.
|
||||
- `verbatim` {boolean} When `true`, the `Promise` is resolved with IPv4 and
|
||||
IPv6 addresses in the order the DNS resolver returned them. When `false`,
|
||||
IPv4 addresses are placed before IPv6 addresses.
|
||||
**Default:** currently `false` (addresses are reordered) but this is
|
||||
expected to change in the not too distant future.
|
||||
New code should use `{ verbatim: true }`.
|
||||
|
||||
Resolves a hostname (e.g. `'nodejs.org'`) into the first found A (IPv4) or
|
||||
AAAA (IPv6) record. All `option` properties are optional. If `options` is an
|
||||
integer, then it must be `4` or `6` – if `options` is not provided, then IPv4
|
||||
and IPv6 addresses are both returned if found.
|
||||
|
||||
With the `all` option set to `true`, the `Promise` is resolved with `addresses`
|
||||
being an array of objects with the properties `address` and `family`.
|
||||
|
||||
On error, the `Promise` is rejected with an [`Error`][] object, where `err.code`
|
||||
is the error code.
|
||||
Keep in mind that `err.code` will be set to `'ENOENT'` not only when
|
||||
the hostname does not exist but also when the lookup fails in other ways
|
||||
such as no available file descriptors.
|
||||
|
||||
[`dnsPromises.lookup()`][] does not necessarily have anything to do with the DNS
|
||||
protocol. The implementation uses an operating system facility that can
|
||||
associate names with addresses, and vice versa. This implementation can have
|
||||
subtle but important consequences on the behavior of any Node.js program. Please
|
||||
take some time to consult the [Implementation considerations section][] before
|
||||
using `dnsPromises.lookup()`.
|
||||
|
||||
Example usage:
|
||||
|
||||
```js
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
const options = {
|
||||
family: 6,
|
||||
hints: dns.ADDRCONFIG | dns.V4MAPPED,
|
||||
};
|
||||
|
||||
dnsPromises.lookup('example.com', options).then((result) => {
|
||||
console.log('address: %j family: IPv%s', result.address, result.family);
|
||||
// address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6
|
||||
});
|
||||
|
||||
// When options.all is true, the result will be an Array.
|
||||
options.all = true;
|
||||
dnsPromises.lookup('example.com', options).then((result) => {
|
||||
console.log('addresses: %j', result);
|
||||
// addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}]
|
||||
});
|
||||
```
|
||||
|
||||
### dnsPromises.lookupService(address, port)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `address` {string}
|
||||
- `port` {number}
|
||||
|
||||
Resolves the given `address` and `port` into a hostname and service using
|
||||
the operating system's underlying `getnameinfo` implementation.
|
||||
|
||||
If `address` is not a valid IP address, a `TypeError` will be thrown.
|
||||
The `port` will be coerced to a number. If it is not a legal port, a `TypeError`
|
||||
will be thrown.
|
||||
|
||||
On error, the `Promise` is rejected with an [`Error`][] object, where `err.code`
|
||||
is the error code.
|
||||
|
||||
```js
|
||||
const dnsPromises = require('dns').promises;
|
||||
dnsPromises.lookupService('127.0.0.1', 22).then((result) => {
|
||||
console.log(result.hostname, result.service);
|
||||
// Prints: localhost ssh
|
||||
});
|
||||
```
|
||||
|
||||
### dnsPromises.resolve(hostname[, rrtype])
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string} Hostname to resolve.
|
||||
- `rrtype` {string} Resource record type. **Default:** `'A'`.
|
||||
|
||||
Uses the DNS protocol to resolve a hostname (e.g. `'nodejs.org'`) into an array
|
||||
of the resource records. When successful, the `Promise` is resolved with an
|
||||
array of resource records. The type and structure of individual results vary
|
||||
based on `rrtype`:
|
||||
|
||||
| `rrtype` | `records` contains | Result type | Shorthand method |
|
||||
|-----------|--------------------------------|-------------|--------------------------|
|
||||
| `'A'` | IPv4 addresses (default) | {string} | [`dnsPromises.resolve4()`][] |
|
||||
| `'AAAA'` | IPv6 addresses | {string} | [`dnsPromises.resolve6()`][] |
|
||||
| `'CNAME'` | canonical name records | {string} | [`dnsPromises.resolveCname()`][] |
|
||||
| `'MX'` | mail exchange records | {Object} | [`dnsPromises.resolveMx()`][] |
|
||||
| `'NAPTR'` | name authority pointer records | {Object} | [`dnsPromises.resolveNaptr()`][] |
|
||||
| `'NS'` | name server records | {string} | [`dnsPromises.resolveNs()`][] |
|
||||
| `'PTR'` | pointer records | {string} | [`dnsPromises.resolvePtr()`][] |
|
||||
| `'SOA'` | start of authority records | {Object} | [`dnsPromises.resolveSoa()`][] |
|
||||
| `'SRV'` | service records | {Object} | [`dnsPromises.resolveSrv()`][] |
|
||||
| `'TXT'` | text records | {string[]} | [`dnsPromises.resolveTxt()`][] |
|
||||
| `'ANY'` | any records | {Object} | [`dnsPromises.resolveAny()`][] |
|
||||
|
||||
On error, the `Promise` is rejected with an [`Error`][] object, where `err.code`
|
||||
is one of the [DNS error codes](#dns_error_codes).
|
||||
|
||||
### dnsPromises.resolve4(hostname[, options])
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string} Hostname to resolve.
|
||||
- `options` {Object}
|
||||
- `ttl` {boolean} Retrieve the Time-To-Live value (TTL) of each record.
|
||||
When `true`, the `Promise` is resolved with an array of
|
||||
`{ address: '1.2.3.4', ttl: 60 }` objects rather than an array of strings,
|
||||
with the TTL expressed in seconds.
|
||||
|
||||
Uses the DNS protocol to resolve IPv4 addresses (`A` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of IPv4
|
||||
addresses (e.g. `['74.125.79.104', '74.125.79.105', '74.125.79.106']`).
|
||||
|
||||
### dnsPromises.resolve6(hostname[, options])
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string} Hostname to resolve.
|
||||
- `options` {Object}
|
||||
- `ttl` {boolean} Retrieve the Time-To-Live value (TTL) of each record.
|
||||
When `true`, the `Promise` is resolved with an array of
|
||||
`{ address: '0:1:2:3:4:5:6:7', ttl: 60 }` objects rather than an array of
|
||||
strings, with the TTL expressed in seconds.
|
||||
|
||||
Uses the DNS protocol to resolve IPv6 addresses (`AAAA` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of IPv6
|
||||
addresses.
|
||||
|
||||
### dnsPromises.resolveCname(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve `CNAME` records for the `hostname`. On success,
|
||||
the `Promise` is resolved with an array of canonical name records available for
|
||||
the `hostname` (e.g. `['bar.example.com']`).
|
||||
|
||||
### dnsPromises.resolveMx(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve mail exchange records (`MX` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of objects
|
||||
containing both a `priority` and `exchange` property (e.g.
|
||||
`[{priority: 10, exchange: 'mx.example.com'}, ...]`).
|
||||
|
||||
### dnsPromises.resolveNaptr(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve regular expression based records (`NAPTR`
|
||||
records) for the `hostname`. On success, the `Promise` is resolved with an array
|
||||
of objects with the following properties:
|
||||
|
||||
* `flags`
|
||||
* `service`
|
||||
* `regexp`
|
||||
* `replacement`
|
||||
* `order`
|
||||
* `preference`
|
||||
|
||||
<!-- eslint-skip -->
|
||||
```js
|
||||
{
|
||||
flags: 's',
|
||||
service: 'SIP+D2U',
|
||||
regexp: '',
|
||||
replacement: '_sip._udp.example.com',
|
||||
order: 30,
|
||||
preference: 100
|
||||
}
|
||||
```
|
||||
|
||||
### dnsPromises.resolveNs(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve name server records (`NS` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of name server
|
||||
records available for `hostname` (e.g.
|
||||
`['ns1.example.com', 'ns2.example.com']`).
|
||||
|
||||
### dnsPromises.resolvePtr(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve pointer records (`PTR` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of strings
|
||||
containing the reply records.
|
||||
|
||||
### dnsPromises.resolveSoa(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve a start of authority record (`SOA` record) for
|
||||
the `hostname`. On success, the `Promise` is resolved with an object with the
|
||||
following properties:
|
||||
|
||||
* `nsname`
|
||||
* `hostmaster`
|
||||
* `serial`
|
||||
* `refresh`
|
||||
* `retry`
|
||||
* `expire`
|
||||
* `minttl`
|
||||
|
||||
<!-- eslint-skip -->
|
||||
```js
|
||||
{
|
||||
nsname: 'ns.example.com',
|
||||
hostmaster: 'root.example.com',
|
||||
serial: 2013101809,
|
||||
refresh: 10000,
|
||||
retry: 2400,
|
||||
expire: 604800,
|
||||
minttl: 3600
|
||||
}
|
||||
```
|
||||
|
||||
### dnsPromises.resolveSrv(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve service records (`SRV` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with an array of objects with
|
||||
the following properties:
|
||||
|
||||
* `priority`
|
||||
* `weight`
|
||||
* `port`
|
||||
* `name`
|
||||
|
||||
<!-- eslint-skip -->
|
||||
```js
|
||||
{
|
||||
priority: 10,
|
||||
weight: 5,
|
||||
port: 21223,
|
||||
name: 'service.example.com'
|
||||
}
|
||||
```
|
||||
|
||||
### dnsPromises.resolveTxt(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve text queries (`TXT` records) for the
|
||||
`hostname`. On success, the `Promise` is resolved with a two-dimensional array
|
||||
of the text records available for `hostname` (e.g.
|
||||
`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of
|
||||
one record. Depending on the use case, these could be either joined together or
|
||||
treated separately.
|
||||
|
||||
### dnsPromises.resolveAny(hostname)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `hostname` {string}
|
||||
|
||||
Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query).
|
||||
On success, the `Promise` is resolved with an array containing various types of
|
||||
records. Each object has a property `type` that indicates the type of the
|
||||
current record. And depending on the `type`, additional properties will be
|
||||
present on the object:
|
||||
|
||||
| Type | Properties |
|
||||
|------|------------|
|
||||
| `'A'` | `address`/`ttl` |
|
||||
| `'AAAA'` | `address`/`ttl` |
|
||||
| `'CNAME'` | `value` |
|
||||
| `'MX'` | Refer to [`dnsPromises.resolveMx()`][] |
|
||||
| `'NAPTR'` | Refer to [`dnsPromises.resolveNaptr()`][] |
|
||||
| `'NS'` | `value` |
|
||||
| `'PTR'` | `value` |
|
||||
| `'SOA'` | Refer to [`dnsPromises.resolveSoa()`][] |
|
||||
| `'SRV'` | Refer to [`dnsPromises.resolveSrv()`][] |
|
||||
| `'TXT'` | This type of record contains an array property called `entries` which refers to [`dnsPromises.resolveTxt()`][], e.g. `{ entries: ['...'], type: 'TXT' }` |
|
||||
|
||||
Here is an example of the result object:
|
||||
|
||||
<!-- eslint-disable semi -->
|
||||
```js
|
||||
[ { type: 'A', address: '127.0.0.1', ttl: 299 },
|
||||
{ type: 'CNAME', value: 'example.com' },
|
||||
{ type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
|
||||
{ type: 'NS', value: 'ns1.example.com' },
|
||||
{ type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
|
||||
{ type: 'SOA',
|
||||
nsname: 'ns1.example.com',
|
||||
hostmaster: 'admin.example.com',
|
||||
serial: 156696742,
|
||||
refresh: 900,
|
||||
retry: 900,
|
||||
expire: 1800,
|
||||
minttl: 60 } ]
|
||||
```
|
||||
|
||||
### dnsPromises.reverse(ip)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `ip` {string}
|
||||
|
||||
Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an
|
||||
array of hostnames.
|
||||
|
||||
On error, the `Promise` is rejected with an [`Error`][] object, where `err.code`
|
||||
is one of the [DNS error codes](#dns_error_codes).
|
||||
|
||||
### dnsPromises.setServers(servers)
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
- `servers` {string[]} array of [rfc5952][] formatted addresses
|
||||
|
||||
Sets the IP address and port of servers to be used when performing DNS
|
||||
resolution. The `servers` argument is an array of [rfc5952][] formatted
|
||||
addresses. If the port is the IANA default DNS port (53) it can be omitted.
|
||||
|
||||
```js
|
||||
dnsPromises.setServers([
|
||||
'4.4.4.4',
|
||||
'[2001:4860:4860::8888]',
|
||||
'4.4.4.4:1053',
|
||||
'[2001:4860:4860::8888]:1053'
|
||||
]);
|
||||
```
|
||||
|
||||
An error will be thrown if an invalid address is provided.
|
||||
|
||||
The `dnsPromises.setServers()` method must not be called while a DNS query is in
|
||||
progress.
|
||||
|
||||
## Error codes
|
||||
|
||||
Each DNS query can return one of the following error codes:
|
||||
@ -659,6 +1109,22 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
|
||||
[`dns.resolveTxt()`]: #dns_dns_resolvetxt_hostname_callback
|
||||
[`dns.reverse()`]: #dns_dns_reverse_ip_callback
|
||||
[`dns.setServers()`]: #dns_dns_setservers_servers
|
||||
[`dnsPromises.getServers()`]: #dns_dnspromises_getservers
|
||||
[`dnsPromises.lookup()`]: #dns_dnspromises_lookup_hostname_options
|
||||
[`dnsPromises.resolve()`]: #dns_dnspromises_resolve_hostname_rrtype
|
||||
[`dnsPromises.resolve4()`]: #dns_dnspromises_resolve4_hostname_options
|
||||
[`dnsPromises.resolve6()`]: #dns_dnspromises_resolve6_hostname_options
|
||||
[`dnsPromises.resolveAny()`]: #dns_dnspromises_resolveany_hostname
|
||||
[`dnsPromises.resolveCname()`]: #dns_dnspromises_resolvecname_hostname
|
||||
[`dnsPromises.resolveMx()`]: #dns_dnspromises_resolvemx_hostname
|
||||
[`dnsPromises.resolveNaptr()`]: #dns_dnspromises_resolvenaptr_hostname
|
||||
[`dnsPromises.resolveNs()`]: #dns_dnspromises_resolvens_hostname
|
||||
[`dnsPromises.resolvePtr()`]: #dns_dnspromises_resolveptr_hostname
|
||||
[`dnsPromises.resolveSoa()`]: #dns_dnspromises_resolvesoa_hostname
|
||||
[`dnsPromises.resolveSrv()`]: #dns_dnspromises_resolvesrv_hostname
|
||||
[`dnsPromises.resolveTxt()`]: #dns_dnspromises_resolvetxt_hostname
|
||||
[`dnsPromises.reverse()`]: #dns_dnspromises_reverse_ip
|
||||
[`dnsPromises.setServers()`]: #dns_dnspromises_setservers_servers
|
||||
[`socket.connect()`]: net.html#net_socket_connect_options_connectlistener
|
||||
[`util.promisify()`]: util.html#util_util_promisify_original
|
||||
[DNS error codes]: #dns_error_codes
|
||||
|
149
lib/dns.js
149
lib/dns.js
@ -26,10 +26,15 @@ const { isIP, isIPv4, isLegalPort } = require('internal/net');
|
||||
const { customPromisifyArgs } = require('internal/util');
|
||||
const errors = require('internal/errors');
|
||||
const {
|
||||
ERR_DNS_SET_SERVERS_FAILED,
|
||||
bindDefaultResolver,
|
||||
getDefaultResolver,
|
||||
setDefaultResolver,
|
||||
Resolver,
|
||||
validateHints
|
||||
} = require('internal/dns/utils');
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_CALLBACK,
|
||||
ERR_INVALID_IP_ADDRESS,
|
||||
ERR_INVALID_OPT_VALUE,
|
||||
ERR_MISSING_ARGS,
|
||||
ERR_SOCKET_BAD_PORT
|
||||
@ -39,12 +44,13 @@ const {
|
||||
GetAddrInfoReqWrap,
|
||||
GetNameInfoReqWrap,
|
||||
QueryReqWrap,
|
||||
ChannelWrap,
|
||||
} = cares;
|
||||
|
||||
const IANA_DNS_PORT = 53;
|
||||
const dnsException = errors.dnsException;
|
||||
|
||||
let promisesWarn = true;
|
||||
let promises; // Lazy loaded
|
||||
|
||||
function onlookup(err, addresses) {
|
||||
if (err) {
|
||||
return this.callback(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
@ -97,12 +103,7 @@ function lookup(hostname, options, callback) {
|
||||
all = options.all === true;
|
||||
verbatim = options.verbatim === true;
|
||||
|
||||
if (hints !== 0 &&
|
||||
hints !== cares.AI_ADDRCONFIG &&
|
||||
hints !== cares.AI_V4MAPPED &&
|
||||
hints !== (cares.AI_ADDRCONFIG | cares.AI_V4MAPPED)) {
|
||||
throw new ERR_INVALID_OPT_VALUE('hints', hints);
|
||||
}
|
||||
validateHints(hints);
|
||||
} else {
|
||||
family = options >>> 0;
|
||||
}
|
||||
@ -197,17 +198,6 @@ function onresolve(err, result, ttls) {
|
||||
this.callback(null, result);
|
||||
}
|
||||
|
||||
// Resolver instances correspond 1:1 to c-ares channels.
|
||||
class Resolver {
|
||||
constructor() {
|
||||
this._handle = new ChannelWrap();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._handle.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function resolver(bindingName) {
|
||||
function query(name, /* options, */ callback) {
|
||||
var options;
|
||||
@ -270,101 +260,15 @@ function resolve(hostname, rrtype, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Resolver.prototype.getServers = getServers;
|
||||
function getServers() {
|
||||
const ret = this._handle.getServers();
|
||||
return ret.map((val) => {
|
||||
if (!val[1] || val[1] === IANA_DNS_PORT) return val[0];
|
||||
|
||||
const host = isIP(val[0]) === 6 ? `[${val[0]}]` : val[0];
|
||||
return `${host}:${val[1]}`;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Resolver.prototype.setServers = setServers;
|
||||
function setServers(servers) {
|
||||
// cache the original servers because in the event of an error setting the
|
||||
// servers cares won't have any servers available for resolution
|
||||
const orig = this._handle.getServers();
|
||||
const newSet = [];
|
||||
const IPv6RE = /^\[([^[\]]*)\]/;
|
||||
const addrSplitRE = /(^.+?)(?::(\d+))?$/;
|
||||
|
||||
servers.forEach((serv) => {
|
||||
var ipVersion = isIP(serv);
|
||||
if (ipVersion !== 0)
|
||||
return newSet.push([ipVersion, serv, IANA_DNS_PORT]);
|
||||
|
||||
const match = serv.match(IPv6RE);
|
||||
// we have an IPv6 in brackets
|
||||
if (match) {
|
||||
ipVersion = isIP(match[1]);
|
||||
if (ipVersion !== 0) {
|
||||
const port =
|
||||
parseInt(serv.replace(addrSplitRE, '$2')) ||
|
||||
IANA_DNS_PORT;
|
||||
return newSet.push([ipVersion, match[1], port]);
|
||||
}
|
||||
}
|
||||
|
||||
// addr::port
|
||||
const addrSplitMatch = serv.match(addrSplitRE);
|
||||
if (addrSplitMatch) {
|
||||
const hostIP = addrSplitMatch[1];
|
||||
const port = addrSplitMatch[2] || IANA_DNS_PORT;
|
||||
|
||||
ipVersion = isIP(hostIP);
|
||||
if (ipVersion !== 0) {
|
||||
return newSet.push([ipVersion, hostIP, parseInt(port)]);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ERR_INVALID_IP_ADDRESS(serv);
|
||||
});
|
||||
|
||||
const errorNumber = this._handle.setServers(newSet);
|
||||
|
||||
if (errorNumber !== 0) {
|
||||
// reset the servers to the old servers, because ares probably unset them
|
||||
this._handle.setServers(orig.join(','));
|
||||
|
||||
var err = cares.strerror(errorNumber);
|
||||
throw new ERR_DNS_SET_SERVERS_FAILED(err, servers);
|
||||
}
|
||||
}
|
||||
|
||||
let defaultResolver = new Resolver();
|
||||
|
||||
const resolverKeys = [
|
||||
'getServers',
|
||||
'resolve',
|
||||
'resolveAny',
|
||||
'resolve4',
|
||||
'resolve6',
|
||||
'resolveCname',
|
||||
'resolveMx',
|
||||
'resolveNs',
|
||||
'resolveTxt',
|
||||
'resolveSrv',
|
||||
'resolvePtr',
|
||||
'resolveNaptr',
|
||||
'resolveSoa',
|
||||
'reverse'
|
||||
];
|
||||
|
||||
function setExportsFunctions() {
|
||||
resolverKeys.forEach((key) => {
|
||||
module.exports[key] = defaultResolver[key].bind(defaultResolver);
|
||||
});
|
||||
}
|
||||
|
||||
function defaultResolverSetServers(servers) {
|
||||
const resolver = new Resolver();
|
||||
|
||||
resolver.setServers(servers);
|
||||
defaultResolver = resolver;
|
||||
setExportsFunctions();
|
||||
setDefaultResolver(resolver);
|
||||
bindDefaultResolver(module.exports, Resolver.prototype);
|
||||
|
||||
if (promises !== undefined)
|
||||
bindDefaultResolver(promises, promises.Resolver.prototype);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -405,4 +309,21 @@ module.exports = {
|
||||
CANCELLED: 'ECANCELLED'
|
||||
};
|
||||
|
||||
setExportsFunctions();
|
||||
bindDefaultResolver(module.exports, getDefaultResolver());
|
||||
|
||||
Object.defineProperties(module.exports, {
|
||||
promises: {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
get() {
|
||||
if (promisesWarn) {
|
||||
promises = require('internal/dns/promises');
|
||||
promises.setServers = defaultResolverSetServers;
|
||||
promisesWarn = false;
|
||||
process.emitWarning('The dns.promises API is experimental',
|
||||
'ExperimentalWarning');
|
||||
}
|
||||
return promises;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
249
lib/internal/dns/promises.js
Normal file
249
lib/internal/dns/promises.js
Normal file
@ -0,0 +1,249 @@
|
||||
'use strict';
|
||||
const {
|
||||
bindDefaultResolver,
|
||||
Resolver: CallbackResolver,
|
||||
validateHints
|
||||
} = require('internal/dns/utils');
|
||||
const { codes, dnsException } = require('internal/errors');
|
||||
const { isIP, isIPv4, isLegalPort } = require('internal/net');
|
||||
const {
|
||||
getaddrinfo,
|
||||
getnameinfo,
|
||||
ChannelWrap,
|
||||
GetAddrInfoReqWrap,
|
||||
GetNameInfoReqWrap,
|
||||
QueryReqWrap
|
||||
} = process.binding('cares_wrap');
|
||||
const {
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_OPT_VALUE,
|
||||
ERR_MISSING_ARGS,
|
||||
ERR_SOCKET_BAD_PORT
|
||||
} = codes;
|
||||
|
||||
|
||||
function onlookup(err, addresses) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
const family = this.family ? this.family : isIPv4(addresses[0]) ? 4 : 6;
|
||||
this.resolve({ address: addresses[0], family });
|
||||
}
|
||||
|
||||
function onlookupall(err, addresses) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getaddrinfo', this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
const family = this.family;
|
||||
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
const address = addresses[i];
|
||||
|
||||
addresses[i] = {
|
||||
address,
|
||||
family: family ? family : isIPv4(addresses[i]) ? 4 : 6
|
||||
};
|
||||
}
|
||||
|
||||
this.resolve(addresses);
|
||||
}
|
||||
|
||||
function createLookupPromise(family, hostname, all, hints, verbatim) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!hostname) {
|
||||
if (all)
|
||||
resolve([]);
|
||||
else
|
||||
resolve({ address: null, family: family === 6 ? 6 : 4 });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const matchedFamily = isIP(hostname);
|
||||
|
||||
if (matchedFamily !== 0) {
|
||||
const result = { address: hostname, family: matchedFamily };
|
||||
if (all)
|
||||
resolve([result]);
|
||||
else
|
||||
resolve(result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const req = new GetAddrInfoReqWrap();
|
||||
|
||||
req.family = family;
|
||||
req.hostname = hostname;
|
||||
req.oncomplete = all ? onlookupall : onlookup;
|
||||
req.resolve = resolve;
|
||||
req.reject = reject;
|
||||
|
||||
const err = getaddrinfo(req, hostname, family, hints, verbatim);
|
||||
|
||||
if (err) {
|
||||
reject(dnsException(err, 'getaddrinfo', hostname));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function lookup(hostname, options) {
|
||||
var hints = 0;
|
||||
var family = -1;
|
||||
var all = false;
|
||||
var verbatim = false;
|
||||
|
||||
// Parse arguments
|
||||
if (hostname && typeof hostname !== 'string') {
|
||||
throw new ERR_INVALID_ARG_TYPE('hostname', ['string', 'falsy'], hostname);
|
||||
} else if (options !== null && typeof options === 'object') {
|
||||
hints = options.hints >>> 0;
|
||||
family = options.family >>> 0;
|
||||
all = options.all === true;
|
||||
verbatim = options.verbatim === true;
|
||||
|
||||
validateHints(hints);
|
||||
} else {
|
||||
family = options >>> 0;
|
||||
}
|
||||
|
||||
if (family !== 0 && family !== 4 && family !== 6)
|
||||
throw new ERR_INVALID_OPT_VALUE('family', family);
|
||||
|
||||
return createLookupPromise(family, hostname, all, hints, verbatim);
|
||||
}
|
||||
|
||||
|
||||
function onlookupservice(err, hostname, service) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, 'getnameinfo', this.host));
|
||||
return;
|
||||
}
|
||||
|
||||
this.resolve({ hostname, service });
|
||||
}
|
||||
|
||||
function createLookupServicePromise(host, port) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = new GetNameInfoReqWrap();
|
||||
|
||||
req.host = host;
|
||||
req.port = port;
|
||||
req.oncomplete = onlookupservice;
|
||||
req.resolve = resolve;
|
||||
req.reject = reject;
|
||||
|
||||
const err = getnameinfo(req, host, port);
|
||||
|
||||
if (err)
|
||||
reject(dnsException(err, 'getnameinfo', host));
|
||||
});
|
||||
}
|
||||
|
||||
function lookupService(host, port) {
|
||||
if (arguments.length !== 2)
|
||||
throw new ERR_MISSING_ARGS('host', 'port');
|
||||
|
||||
if (isIP(host) === 0)
|
||||
throw new ERR_INVALID_OPT_VALUE('host', host);
|
||||
|
||||
if (!isLegalPort(port))
|
||||
throw new ERR_SOCKET_BAD_PORT(port);
|
||||
|
||||
return createLookupServicePromise(host, +port);
|
||||
}
|
||||
|
||||
|
||||
function onresolve(err, result, ttls) {
|
||||
if (err) {
|
||||
this.reject(dnsException(err, this.bindingName, this.hostname));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ttls && this.ttl)
|
||||
result = result.map((address, index) => ({ address, ttl: ttls[index] }));
|
||||
|
||||
this.resolve(result);
|
||||
}
|
||||
|
||||
function createResolverPromise(resolver, bindingName, hostname, ttl) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = new QueryReqWrap();
|
||||
|
||||
req.bindingName = bindingName;
|
||||
req.hostname = hostname;
|
||||
req.oncomplete = onresolve;
|
||||
req.resolve = resolve;
|
||||
req.reject = reject;
|
||||
req.ttl = ttl;
|
||||
|
||||
const err = resolver._handle[bindingName](req, hostname);
|
||||
|
||||
if (err)
|
||||
reject(dnsException(err, bindingName, hostname));
|
||||
});
|
||||
}
|
||||
|
||||
function resolver(bindingName) {
|
||||
function query(name, options) {
|
||||
if (typeof name !== 'string') {
|
||||
throw new ERR_INVALID_ARG_TYPE('name', 'string', name);
|
||||
}
|
||||
|
||||
const ttl = !!(options && options.ttl);
|
||||
return createResolverPromise(this, bindingName, name, ttl);
|
||||
}
|
||||
|
||||
Object.defineProperty(query, 'name', { value: bindingName });
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
const resolveMap = Object.create(null);
|
||||
|
||||
// Resolver instances correspond 1:1 to c-ares channels.
|
||||
class Resolver {
|
||||
constructor() {
|
||||
this._handle = new ChannelWrap();
|
||||
}
|
||||
}
|
||||
|
||||
Resolver.prototype.cancel = CallbackResolver.prototype.cancel;
|
||||
Resolver.prototype.getServers = CallbackResolver.prototype.getServers;
|
||||
Resolver.prototype.setServers = CallbackResolver.prototype.setServers;
|
||||
Resolver.prototype.resolveAny = resolveMap.ANY = resolver('queryAny');
|
||||
Resolver.prototype.resolve4 = resolveMap.A = resolver('queryA');
|
||||
Resolver.prototype.resolve6 = resolveMap.AAAA = resolver('queryAaaa');
|
||||
Resolver.prototype.resolveCname = resolveMap.CNAME = resolver('queryCname');
|
||||
Resolver.prototype.resolveMx = resolveMap.MX = resolver('queryMx');
|
||||
Resolver.prototype.resolveNs = resolveMap.NS = resolver('queryNs');
|
||||
Resolver.prototype.resolveTxt = resolveMap.TXT = resolver('queryTxt');
|
||||
Resolver.prototype.resolveSrv = resolveMap.SRV = resolver('querySrv');
|
||||
Resolver.prototype.resolvePtr = resolveMap.PTR = resolver('queryPtr');
|
||||
Resolver.prototype.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr');
|
||||
Resolver.prototype.resolveSoa = resolveMap.SOA = resolver('querySoa');
|
||||
Resolver.prototype.reverse = resolver('getHostByAddr');
|
||||
Resolver.prototype.resolve = function resolve(hostname, rrtype) {
|
||||
var resolver;
|
||||
|
||||
if (typeof rrtype === 'string') {
|
||||
resolver = resolveMap[rrtype];
|
||||
|
||||
if (typeof resolver !== 'function')
|
||||
throw new ERR_INVALID_OPT_VALUE('rrtype', rrtype);
|
||||
} else if (rrtype === undefined) {
|
||||
resolver = resolveMap.A;
|
||||
} else {
|
||||
throw new ERR_INVALID_ARG_TYPE('rrtype', 'string', rrtype);
|
||||
}
|
||||
|
||||
return resolver.call(this, hostname);
|
||||
};
|
||||
|
||||
|
||||
module.exports = { lookup, lookupService, Resolver };
|
||||
bindDefaultResolver(module.exports, Resolver.prototype);
|
141
lib/internal/dns/utils.js
Normal file
141
lib/internal/dns/utils.js
Normal file
@ -0,0 +1,141 @@
|
||||
'use strict';
|
||||
const errors = require('internal/errors');
|
||||
const { isIP } = require('internal/net');
|
||||
const {
|
||||
ChannelWrap,
|
||||
strerror,
|
||||
AI_ADDRCONFIG,
|
||||
AI_V4MAPPED
|
||||
} = process.binding('cares_wrap');
|
||||
const IANA_DNS_PORT = 53;
|
||||
const IPv6RE = /^\[([^[\]]*)\]/;
|
||||
const addrSplitRE = /(^.+?)(?::(\d+))?$/;
|
||||
const {
|
||||
ERR_DNS_SET_SERVERS_FAILED,
|
||||
ERR_INVALID_IP_ADDRESS,
|
||||
ERR_INVALID_OPT_VALUE
|
||||
} = errors.codes;
|
||||
|
||||
// Resolver instances correspond 1:1 to c-ares channels.
|
||||
class Resolver {
|
||||
constructor() {
|
||||
this._handle = new ChannelWrap();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._handle.cancel();
|
||||
}
|
||||
|
||||
getServers() {
|
||||
return this._handle.getServers().map((val) => {
|
||||
if (!val[1] || val[1] === IANA_DNS_PORT)
|
||||
return val[0];
|
||||
|
||||
const host = isIP(val[0]) === 6 ? `[${val[0]}]` : val[0];
|
||||
return `${host}:${val[1]}`;
|
||||
});
|
||||
}
|
||||
|
||||
setServers(servers) {
|
||||
// Cache the original servers because in the event of an error while
|
||||
// setting the servers, c-ares won't have any servers available for
|
||||
// resolution.
|
||||
const orig = this._handle.getServers();
|
||||
const newSet = [];
|
||||
|
||||
servers.forEach((serv) => {
|
||||
var ipVersion = isIP(serv);
|
||||
|
||||
if (ipVersion !== 0)
|
||||
return newSet.push([ipVersion, serv, IANA_DNS_PORT]);
|
||||
|
||||
const match = serv.match(IPv6RE);
|
||||
|
||||
// Check for an IPv6 in brackets.
|
||||
if (match) {
|
||||
ipVersion = isIP(match[1]);
|
||||
|
||||
if (ipVersion !== 0) {
|
||||
const port =
|
||||
parseInt(serv.replace(addrSplitRE, '$2')) ||
|
||||
IANA_DNS_PORT;
|
||||
return newSet.push([ipVersion, match[1], port]);
|
||||
}
|
||||
}
|
||||
|
||||
// addr::port
|
||||
const addrSplitMatch = serv.match(addrSplitRE);
|
||||
|
||||
if (addrSplitMatch) {
|
||||
const hostIP = addrSplitMatch[1];
|
||||
const port = addrSplitMatch[2] || IANA_DNS_PORT;
|
||||
|
||||
ipVersion = isIP(hostIP);
|
||||
|
||||
if (ipVersion !== 0) {
|
||||
return newSet.push([ipVersion, hostIP, parseInt(port)]);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ERR_INVALID_IP_ADDRESS(serv);
|
||||
});
|
||||
|
||||
const errorNumber = this._handle.setServers(newSet);
|
||||
|
||||
if (errorNumber !== 0) {
|
||||
// Reset the servers to the old servers, because ares probably unset them.
|
||||
this._handle.setServers(orig.join(','));
|
||||
const err = strerror(errorNumber);
|
||||
throw new ERR_DNS_SET_SERVERS_FAILED(err, servers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let defaultResolver = new Resolver();
|
||||
const resolverKeys = [
|
||||
'getServers',
|
||||
'resolve',
|
||||
'resolveAny',
|
||||
'resolve4',
|
||||
'resolve6',
|
||||
'resolveCname',
|
||||
'resolveMx',
|
||||
'resolveNs',
|
||||
'resolveTxt',
|
||||
'resolveSrv',
|
||||
'resolvePtr',
|
||||
'resolveNaptr',
|
||||
'resolveSoa',
|
||||
'reverse'
|
||||
];
|
||||
|
||||
function getDefaultResolver() {
|
||||
return defaultResolver;
|
||||
}
|
||||
|
||||
function setDefaultResolver(resolver) {
|
||||
defaultResolver = resolver;
|
||||
}
|
||||
|
||||
function bindDefaultResolver(target, source) {
|
||||
resolverKeys.forEach((key) => {
|
||||
target[key] = source[key].bind(defaultResolver);
|
||||
});
|
||||
}
|
||||
|
||||
function validateHints(hints) {
|
||||
if (hints !== 0 &&
|
||||
hints !== AI_ADDRCONFIG &&
|
||||
hints !== AI_V4MAPPED &&
|
||||
hints !== (AI_ADDRCONFIG | AI_V4MAPPED)) {
|
||||
throw new ERR_INVALID_OPT_VALUE('hints', hints);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bindDefaultResolver,
|
||||
getDefaultResolver,
|
||||
setDefaultResolver,
|
||||
validateHints,
|
||||
Resolver
|
||||
};
|
2
node.gyp
2
node.gyp
@ -101,6 +101,8 @@
|
||||
'lib/internal/crypto/sig.js',
|
||||
'lib/internal/crypto/util.js',
|
||||
'lib/internal/constants.js',
|
||||
'lib/internal/dns/promises.js',
|
||||
'lib/internal/dns/utils.js',
|
||||
'lib/internal/encoding.js',
|
||||
'lib/internal/errors.js',
|
||||
'lib/internal/error-serdes.js',
|
||||
|
@ -9,6 +9,9 @@ const net = require('net');
|
||||
let running = false;
|
||||
const queue = [];
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const dnsPromises = dns.promises;
|
||||
const isIPv4 = net.isIPv4;
|
||||
const isIPv6 = net.isIPv6;
|
||||
|
||||
@ -101,93 +104,95 @@ function TEST(f) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(function test_google(done) {
|
||||
function processResult(res) {
|
||||
assert.ok(Array.isArray(res));
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
const types = {};
|
||||
res.forEach((obj) => {
|
||||
types[obj.type] = true;
|
||||
checkers[`check${obj.type}`](obj);
|
||||
});
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
TEST(async function test_google(done) {
|
||||
function validateResult(res) {
|
||||
const types = processResult(res);
|
||||
assert.ok(
|
||||
types.A && types.AAAA && types.MX &&
|
||||
types.NS && types.TXT && types.SOA);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve('google.com', 'ANY'));
|
||||
|
||||
const req = dns.resolve(
|
||||
'google.com',
|
||||
'ANY',
|
||||
common.mustCall(function(err, ret) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ret));
|
||||
assert.ok(ret.length > 0);
|
||||
|
||||
/* current google.com has A / AAAA / MX / NS / TXT and SOA records */
|
||||
const types = {};
|
||||
ret.forEach((obj) => {
|
||||
types[obj.type] = true;
|
||||
checkers[`check${obj.type}`](obj);
|
||||
});
|
||||
assert.ok(
|
||||
types.A && types.AAAA && types.MX &&
|
||||
types.NS && types.TXT && types.SOA);
|
||||
|
||||
validateResult(ret);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_sip2sip_for_naptr(done) {
|
||||
TEST(async function test_sip2sip_for_naptr(done) {
|
||||
function validateResult(res) {
|
||||
const types = processResult(res);
|
||||
assert.ok(types.A && types.NS && types.NAPTR && types.SOA);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve('sip2sip.info', 'ANY'));
|
||||
|
||||
const req = dns.resolve(
|
||||
'sip2sip.info',
|
||||
'ANY',
|
||||
common.mustCall(function(err, ret) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ret));
|
||||
assert.ok(ret.length > 0);
|
||||
|
||||
/* current sip2sip.info has A / NS / NAPTR and SOA records */
|
||||
const types = {};
|
||||
ret.forEach((obj) => {
|
||||
types[obj.type] = true;
|
||||
checkers[`check${obj.type}`](obj);
|
||||
});
|
||||
assert.ok(types.A && types.NS && types.NAPTR && types.SOA);
|
||||
|
||||
validateResult(ret);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_google_for_cname_and_srv(done) {
|
||||
TEST(async function test_google_for_cname_and_srv(done) {
|
||||
function validateResult(res) {
|
||||
const types = processResult(res);
|
||||
assert.ok(types.SRV);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve('_jabber._tcp.google.com', 'ANY'));
|
||||
|
||||
const req = dns.resolve(
|
||||
'_jabber._tcp.google.com',
|
||||
'ANY',
|
||||
common.mustCall(function(err, ret) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ret));
|
||||
assert.ok(ret.length > 0);
|
||||
|
||||
const types = {};
|
||||
ret.forEach((obj) => {
|
||||
types[obj.type] = true;
|
||||
checkers[`check${obj.type}`](obj);
|
||||
});
|
||||
assert.ok(types.SRV);
|
||||
|
||||
validateResult(ret);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_ptr(done) {
|
||||
TEST(async function test_ptr(done) {
|
||||
function validateResult(res) {
|
||||
const types = processResult(res);
|
||||
assert.ok(types.PTR);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve('8.8.8.8.in-addr.arpa', 'ANY'));
|
||||
|
||||
const req = dns.resolve(
|
||||
'8.8.8.8.in-addr.arpa',
|
||||
'ANY',
|
||||
common.mustCall(function(err, ret) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ret));
|
||||
assert.ok(ret.length > 0);
|
||||
|
||||
/* current 8.8.8.8.in-addr.arpa has PTR record */
|
||||
const types = {};
|
||||
ret.forEach((obj) => {
|
||||
types[obj.type] = true;
|
||||
checkers[`check${obj.type}`](obj);
|
||||
});
|
||||
assert.ok(types.PTR);
|
||||
|
||||
validateResult(ret);
|
||||
done();
|
||||
}));
|
||||
|
||||
|
@ -9,6 +9,7 @@ const isIPv4 = net.isIPv4;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const dnsPromises = dns.promises;
|
||||
let running = false;
|
||||
const queue = [];
|
||||
|
||||
@ -38,139 +39,187 @@ function checkWrap(req) {
|
||||
assert.ok(typeof req === 'object');
|
||||
}
|
||||
|
||||
TEST(function test_resolve4(done) {
|
||||
TEST(async function test_resolve4(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
assert.ok(isIPv4(res[i]));
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve4(addresses.INET4_HOST));
|
||||
|
||||
const req = dns.resolve4(
|
||||
addresses.INET4_HOST,
|
||||
common.mustCall((err, ips) => {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
for (let i = 0; i < ips.length; i++) {
|
||||
assert.ok(isIPv4(ips[i]));
|
||||
}
|
||||
|
||||
validateResult(ips);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_reverse_ipv4(done) {
|
||||
TEST(async function test_reverse_ipv4(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
assert.ok(res[i]);
|
||||
assert.ok(typeof res[i] === 'string');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.reverse(addresses.INET4_IP));
|
||||
|
||||
const req = dns.reverse(
|
||||
addresses.INET4_IP,
|
||||
common.mustCall((err, domains) => {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.ok(domains.length > 0);
|
||||
|
||||
for (let i = 0; i < domains.length; i++) {
|
||||
assert.ok(domains[i]);
|
||||
assert.ok(typeof domains[i] === 'string');
|
||||
}
|
||||
|
||||
validateResult(domains);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ipv4_explicit(done) {
|
||||
TEST(async function test_lookup_ipv4_explicit(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(net.isIPv4(res.address));
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET4_HOST, 4));
|
||||
|
||||
const req = dns.lookup(
|
||||
addresses.INET4_HOST, 4,
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(net.isIPv4(ip));
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ipv4_implicit(done) {
|
||||
TEST(async function test_lookup_ipv4_implicit(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(net.isIPv4(res.address));
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET4_HOST));
|
||||
|
||||
const req = dns.lookup(
|
||||
addresses.INET4_HOST,
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(net.isIPv4(ip));
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ipv4_explicit_object(done) {
|
||||
TEST(async function test_lookup_ipv4_explicit_object(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(net.isIPv4(res.address));
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET4_HOST, { family: 4 }));
|
||||
|
||||
const req = dns.lookup(addresses.INET4_HOST, {
|
||||
family: 4
|
||||
}, common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(net.isIPv4(ip));
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ipv4_hint_addrconfig(done) {
|
||||
TEST(async function test_lookup_ipv4_hint_addrconfig(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(net.isIPv4(res.address));
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET4_HOST, {
|
||||
hints: dns.ADDRCONFIG
|
||||
}));
|
||||
|
||||
const req = dns.lookup(addresses.INET4_HOST, {
|
||||
hints: dns.ADDRCONFIG
|
||||
}, common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(net.isIPv4(ip));
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ip_ipv4(done) {
|
||||
TEST(async function test_lookup_ip_ipv4(done) {
|
||||
function validateResult(res) {
|
||||
assert.strictEqual(res.address, '127.0.0.1');
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup('127.0.0.1'));
|
||||
|
||||
const req = dns.lookup('127.0.0.1',
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.strictEqual(ip, '127.0.0.1');
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_localhost_ipv4(done) {
|
||||
TEST(async function test_lookup_localhost_ipv4(done) {
|
||||
function validateResult(res) {
|
||||
assert.strictEqual(res.address, '127.0.0.1');
|
||||
assert.strictEqual(res.family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup('localhost', 4));
|
||||
|
||||
const req = dns.lookup('localhost', 4,
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.strictEqual(ip, '127.0.0.1');
|
||||
assert.strictEqual(family, 4);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_all_ipv4(done) {
|
||||
TEST(async function test_lookup_all_ipv4(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(Array.isArray(res));
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
res.forEach((ip) => {
|
||||
assert.ok(isIPv4(ip.address));
|
||||
assert.strictEqual(ip.family, 4);
|
||||
});
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET4_HOST, {
|
||||
all: true,
|
||||
family: 4
|
||||
}));
|
||||
|
||||
const req = dns.lookup(
|
||||
addresses.INET4_HOST,
|
||||
{ all: true, family: 4 },
|
||||
common.mustCall((err, ips) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
ips.forEach((ip) => {
|
||||
assert.ok(isIPv4(ip.address));
|
||||
assert.strictEqual(ip.family, 4);
|
||||
});
|
||||
|
||||
validateResult(ips);
|
||||
done();
|
||||
})
|
||||
);
|
||||
@ -178,14 +227,20 @@ TEST(function test_lookup_all_ipv4(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookupservice_ip_ipv4(done) {
|
||||
TEST(async function test_lookupservice_ip_ipv4(done) {
|
||||
function validateResult(res) {
|
||||
assert.strictEqual(typeof res.hostname, 'string');
|
||||
assert(res.hostname);
|
||||
assert(['http', 'www', '80'].includes(res.service));
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookupService('127.0.0.1', 80));
|
||||
|
||||
const req = dns.lookupService(
|
||||
'127.0.0.1', 80,
|
||||
common.mustCall((err, host, service) => {
|
||||
common.mustCall((err, hostname, service) => {
|
||||
assert.ifError(err);
|
||||
assert.strictEqual(typeof host, 'string');
|
||||
assert(host);
|
||||
assert(['http', 'www', '80'].includes(service));
|
||||
validateResult({ hostname, service });
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
@ -4,9 +4,12 @@ const { addresses } = require('../common/internet');
|
||||
if (!common.hasIPv6)
|
||||
common.skip('this test, no IPv6 support');
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const assert = require('assert');
|
||||
const dns = require('dns');
|
||||
const net = require('net');
|
||||
const dnsPromises = dns.promises;
|
||||
const isIPv6 = net.isIPv6;
|
||||
|
||||
let running = false;
|
||||
@ -38,49 +41,64 @@ function checkWrap(req) {
|
||||
assert.ok(typeof req === 'object');
|
||||
}
|
||||
|
||||
TEST(function test_resolve6(done) {
|
||||
TEST(async function test_resolve6(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
assert.ok(isIPv6(res[i]));
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve6(addresses.INET6_HOST));
|
||||
|
||||
const req = dns.resolve6(
|
||||
addresses.INET6_HOST,
|
||||
common.mustCall((err, ips) => {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
for (let i = 0; i < ips.length; i++)
|
||||
assert.ok(isIPv6(ips[i]));
|
||||
|
||||
validateResult(ips);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_reverse_ipv6(done) {
|
||||
TEST(async function test_reverse_ipv6(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
assert.ok(typeof res[i] === 'string');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.reverse(addresses.INET6_IP));
|
||||
|
||||
const req = dns.reverse(
|
||||
addresses.INET6_IP,
|
||||
common.mustCall((err, domains) => {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.ok(domains.length > 0);
|
||||
|
||||
for (let i = 0; i < domains.length; i++)
|
||||
assert.ok(typeof domains[i] === 'string');
|
||||
|
||||
validateResult(domains);
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ipv6_explicit(done) {
|
||||
TEST(async function test_lookup_ipv6_explicit(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(isIPv6(res.address));
|
||||
assert.strictEqual(res.family, 6);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET6_HOST, 6));
|
||||
|
||||
const req = dns.lookup(
|
||||
addresses.INET6_HOST,
|
||||
6,
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(isIPv6(ip));
|
||||
assert.strictEqual(family, 6);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
@ -101,14 +119,19 @@ TEST(function test_lookup_ipv6_implicit(done) {
|
||||
});
|
||||
*/
|
||||
|
||||
TEST(function test_lookup_ipv6_explicit_object(done) {
|
||||
TEST(async function test_lookup_ipv6_explicit_object(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(isIPv6(res.address));
|
||||
assert.strictEqual(res.family, 6);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET6_HOST, { family: 6 }));
|
||||
|
||||
const req = dns.lookup(addresses.INET6_HOST, {
|
||||
family: 6
|
||||
}, common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(isIPv6(ip));
|
||||
assert.strictEqual(family, 6);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
@ -143,35 +166,48 @@ TEST(function test_lookup_ipv6_hint(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_ip_ipv6(done) {
|
||||
TEST(async function test_lookup_ip_ipv6(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(isIPv6(res.address));
|
||||
assert.strictEqual(res.family, 6);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup('::1'));
|
||||
|
||||
const req = dns.lookup(
|
||||
'::1',
|
||||
common.mustCall((err, ip, family) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(isIPv6(ip));
|
||||
assert.strictEqual(family, 6);
|
||||
|
||||
validateResult({ address: ip, family });
|
||||
done();
|
||||
}));
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_lookup_all_ipv6(done) {
|
||||
TEST(async function test_lookup_all_ipv6(done) {
|
||||
function validateResult(res) {
|
||||
assert.ok(Array.isArray(res));
|
||||
assert.ok(res.length > 0);
|
||||
|
||||
res.forEach((ip) => {
|
||||
assert.ok(isIPv6(ip.address),
|
||||
`Invalid IPv6: ${ip.address.toString()}`);
|
||||
assert.strictEqual(ip.family, 6);
|
||||
});
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET6_HOST, {
|
||||
all: true,
|
||||
family: 6
|
||||
}));
|
||||
|
||||
const req = dns.lookup(
|
||||
addresses.INET6_HOST,
|
||||
{ all: true, family: 6 },
|
||||
common.mustCall((err, ips) => {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
|
||||
ips.forEach((ip) => {
|
||||
assert.ok(isIPv6(ip.address),
|
||||
`Invalid IPv6: ${ip.address.toString()}`);
|
||||
assert.strictEqual(ip.family, 6);
|
||||
});
|
||||
|
||||
validateResult(ips);
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
@ -1,7 +1,15 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
(async function() {
|
||||
const result = await dnsPromises.resolveTxt('www.microsoft.com');
|
||||
assert.strictEqual(result.length, 0);
|
||||
})();
|
||||
|
||||
dns.resolveTxt('www.microsoft.com', function(err, records) {
|
||||
assert.strictEqual(err, null);
|
||||
|
@ -28,6 +28,7 @@ const net = require('net');
|
||||
const isIPv4 = net.isIPv4;
|
||||
const isIPv6 = net.isIPv6;
|
||||
const util = require('util');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
@ -68,17 +69,18 @@ function checkWrap(req) {
|
||||
|
||||
|
||||
TEST(function test_reverse_bogus(done) {
|
||||
dnsPromises.reverse('bogus ip')
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'EINVAL' }));
|
||||
|
||||
assert.throws(() => {
|
||||
dns.reverse('bogus ip', common.mustNotCall());
|
||||
}, /^Error: getHostByAddr EINVAL bogus ip$/);
|
||||
done();
|
||||
});
|
||||
|
||||
TEST(function test_resolve4_ttl(done) {
|
||||
const req = dns.resolve4(addresses.INET4_HOST, {
|
||||
ttl: true
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolve4_ttl(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
@ -90,18 +92,25 @@ TEST(function test_resolve4_ttl(done) {
|
||||
assert.ok(item.ttl > 0);
|
||||
assert.ok(isIPv4(item.address));
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve4(addresses.INET4_HOST, {
|
||||
ttl: true
|
||||
}));
|
||||
|
||||
const req = dns.resolve4(addresses.INET4_HOST, {
|
||||
ttl: true
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolve6_ttl(done) {
|
||||
const req = dns.resolve6(addresses.INET6_HOST, {
|
||||
ttl: true
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolve6_ttl(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
@ -113,29 +122,42 @@ TEST(function test_resolve6_ttl(done) {
|
||||
assert.ok(item.ttl > 0);
|
||||
assert.ok(isIPv6(item.address));
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolve6(addresses.INET6_HOST, {
|
||||
ttl: true
|
||||
}));
|
||||
|
||||
const req = dns.resolve6(addresses.INET6_HOST, {
|
||||
ttl: true
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveMx(done) {
|
||||
const req = dns.resolveMx(addresses.MX_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolveMx(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const item = result[i];
|
||||
assert.ok(item);
|
||||
assert.strictEqual(typeof item, 'object');
|
||||
|
||||
assert.ok(item.exchange);
|
||||
assert.strictEqual(typeof item.exchange, 'string');
|
||||
|
||||
assert.strictEqual(typeof item.priority, 'number');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveMx(addresses.MX_HOST));
|
||||
|
||||
const req = dns.resolveMx(addresses.MX_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -143,6 +165,10 @@ TEST(function test_resolveMx(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveMx_failure(done) {
|
||||
dnsPromises.resolveMx(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveMx(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -155,17 +181,23 @@ TEST(function test_resolveMx_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveNs(done) {
|
||||
TEST(async function test_resolveNs(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const item = result[i];
|
||||
|
||||
assert.ok(item);
|
||||
assert.strictEqual(typeof item, 'string');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveNs(addresses.NS_HOST));
|
||||
|
||||
const req = dns.resolveNs(addresses.NS_HOST, function(err, names) {
|
||||
assert.ifError(err);
|
||||
assert.ok(names.length > 0);
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const name = names[i];
|
||||
assert.ok(name);
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
}
|
||||
|
||||
validateResult(names);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -173,6 +205,10 @@ TEST(function test_resolveNs(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveNs_failure(done) {
|
||||
dnsPromises.resolveNs(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveNs(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -185,9 +221,8 @@ TEST(function test_resolveNs_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveSrv(done) {
|
||||
const req = dns.resolveSrv(addresses.SRV_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolveSrv(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
@ -202,7 +237,13 @@ TEST(function test_resolveSrv(done) {
|
||||
assert.strictEqual(typeof item.priority, 'number');
|
||||
assert.strictEqual(typeof item.weight, 'number');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveSrv(addresses.SRV_HOST));
|
||||
|
||||
const req = dns.resolveSrv(addresses.SRV_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -210,6 +251,10 @@ TEST(function test_resolveSrv(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveSrv_failure(done) {
|
||||
dnsPromises.resolveSrv(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveSrv(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -222,9 +267,8 @@ TEST(function test_resolveSrv_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolvePtr(done) {
|
||||
const req = dns.resolvePtr(addresses.PTR_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolvePtr(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
@ -232,7 +276,13 @@ TEST(function test_resolvePtr(done) {
|
||||
assert.ok(item);
|
||||
assert.strictEqual(typeof item, 'string');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolvePtr(addresses.PTR_HOST));
|
||||
|
||||
const req = dns.resolvePtr(addresses.PTR_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -240,6 +290,10 @@ TEST(function test_resolvePtr(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolvePtr_failure(done) {
|
||||
dnsPromises.resolvePtr(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolvePtr(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -252,16 +306,14 @@ TEST(function test_resolvePtr_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveNaptr(done) {
|
||||
const req = dns.resolveNaptr(addresses.NAPTR_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolveNaptr(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const item = result[i];
|
||||
assert.ok(item);
|
||||
assert.strictEqual(typeof item, 'object');
|
||||
|
||||
assert.strictEqual(typeof item.flags, 'string');
|
||||
assert.strictEqual(typeof item.service, 'string');
|
||||
assert.strictEqual(typeof item.regexp, 'string');
|
||||
@ -269,7 +321,13 @@ TEST(function test_resolveNaptr(done) {
|
||||
assert.strictEqual(typeof item.order, 'number');
|
||||
assert.strictEqual(typeof item.preference, 'number');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveNaptr(addresses.NAPTR_HOST));
|
||||
|
||||
const req = dns.resolveNaptr(addresses.NAPTR_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -277,6 +335,10 @@ TEST(function test_resolveNaptr(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveNaptr_failure(done) {
|
||||
dnsPromises.resolveNaptr(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveNaptr(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -289,33 +351,31 @@ TEST(function test_resolveNaptr_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveSoa(done) {
|
||||
const req = dns.resolveSoa(addresses.SOA_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
TEST(async function test_resolveSoa(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result);
|
||||
assert.strictEqual(typeof result, 'object');
|
||||
|
||||
assert.strictEqual(typeof result.nsname, 'string');
|
||||
assert.ok(result.nsname.length > 0);
|
||||
|
||||
assert.strictEqual(typeof result.hostmaster, 'string');
|
||||
assert.ok(result.hostmaster.length > 0);
|
||||
|
||||
assert.strictEqual(typeof result.serial, 'number');
|
||||
assert.ok((result.serial > 0) && (result.serial < 4294967295));
|
||||
|
||||
assert.strictEqual(typeof result.refresh, 'number');
|
||||
assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
|
||||
|
||||
assert.strictEqual(typeof result.retry, 'number');
|
||||
assert.ok((result.retry > 0) && (result.retry < 2147483647));
|
||||
|
||||
assert.strictEqual(typeof result.expire, 'number');
|
||||
assert.ok((result.expire > 0) && (result.expire < 2147483647));
|
||||
|
||||
assert.strictEqual(typeof result.minttl, 'number');
|
||||
assert.ok((result.minttl >= 0) && (result.minttl < 2147483647));
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveSoa(addresses.SOA_HOST));
|
||||
|
||||
const req = dns.resolveSoa(addresses.SOA_HOST, function(err, result) {
|
||||
assert.ifError(err);
|
||||
validateResult(result);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -323,6 +383,10 @@ TEST(function test_resolveSoa(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveSoa_failure(done) {
|
||||
dnsPromises.resolveSoa(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveSoa(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -335,17 +399,22 @@ TEST(function test_resolveSoa_failure(done) {
|
||||
checkWrap(req);
|
||||
});
|
||||
|
||||
TEST(function test_resolveCname(done) {
|
||||
const req = dns.resolveCname(addresses.CNAME_HOST, function(err, names) {
|
||||
assert.ifError(err);
|
||||
assert.ok(names.length > 0);
|
||||
TEST(async function test_resolveCname(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const name = names[i];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const name = result[i];
|
||||
assert.ok(name);
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
}
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveCname(addresses.CNAME_HOST));
|
||||
|
||||
const req = dns.resolveCname(addresses.CNAME_HOST, function(err, names) {
|
||||
assert.ifError(err);
|
||||
validateResult(names);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -353,6 +422,10 @@ TEST(function test_resolveCname(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveCname_failure(done) {
|
||||
dnsPromises.resolveCname(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveCname(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -366,12 +439,18 @@ TEST(function test_resolveCname_failure(done) {
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_resolveTxt(done) {
|
||||
TEST(async function test_resolveTxt(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(Array.isArray(result[0]));
|
||||
assert.strictEqual(result.length, 1);
|
||||
assert(result[0][0].startsWith('v=spf1'));
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.resolveTxt(addresses.TXT_HOST));
|
||||
|
||||
const req = dns.resolveTxt(addresses.TXT_HOST, function(err, records) {
|
||||
assert.ifError(err);
|
||||
assert.strictEqual(records.length, 1);
|
||||
assert.ok(util.isArray(records[0]));
|
||||
assert(records[0][0].startsWith('v=spf1'));
|
||||
validateResult(records);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -379,6 +458,10 @@ TEST(function test_resolveTxt(done) {
|
||||
});
|
||||
|
||||
TEST(function test_resolveTxt_failure(done) {
|
||||
dnsPromises.resolveTxt(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.resolveTxt(addresses.INVALID_HOST, function(err, result) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, 'ENOTFOUND');
|
||||
@ -393,6 +476,10 @@ TEST(function test_resolveTxt_failure(done) {
|
||||
|
||||
|
||||
TEST(function test_lookup_failure(done) {
|
||||
dnsPromises.lookup(addresses.INVALID_HOST, 4)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ errno: dns.NOTFOUND }));
|
||||
|
||||
const req = dns.lookup(addresses.INVALID_HOST, 4, (err, ip, family) => {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.errno, dns.NOTFOUND);
|
||||
@ -407,17 +494,23 @@ TEST(function test_lookup_failure(done) {
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_ip_all(done) {
|
||||
TEST(async function test_lookup_ip_all(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.ok(result.length > 0);
|
||||
assert.strictEqual(result[0].address, '127.0.0.1');
|
||||
assert.strictEqual(result[0].family, 4);
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup('127.0.0.1', { all: true }));
|
||||
|
||||
const req = dns.lookup(
|
||||
'127.0.0.1',
|
||||
{ all: true },
|
||||
function(err, ips, family) {
|
||||
assert.ifError(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);
|
||||
|
||||
assert.strictEqual(family, undefined);
|
||||
validateResult(ips);
|
||||
done();
|
||||
}
|
||||
);
|
||||
@ -452,7 +545,9 @@ TEST(function test_lookup_ip_promise(done) {
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_null_all(done) {
|
||||
TEST(async function test_lookup_null_all(done) {
|
||||
assert.deepStrictEqual(await dnsPromises.lookup(null, { all: true }), []);
|
||||
|
||||
const req = dns.lookup(null, { all: true }, function(err, ips, family) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ips));
|
||||
@ -465,15 +560,12 @@ TEST(function test_lookup_null_all(done) {
|
||||
});
|
||||
|
||||
|
||||
TEST(function test_lookup_all_mixed(done) {
|
||||
const req = dns.lookup(addresses.INET_HOST, {
|
||||
all: true
|
||||
}, function(err, ips) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(ips));
|
||||
assert.ok(ips.length > 0);
|
||||
TEST(async function test_lookup_all_mixed(done) {
|
||||
function validateResult(result) {
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.ok(result.length > 0);
|
||||
|
||||
ips.forEach(function(ip) {
|
||||
result.forEach(function(ip) {
|
||||
if (isIPv4(ip.address))
|
||||
assert.strictEqual(ip.family, 4);
|
||||
else if (isIPv6(ip.address))
|
||||
@ -481,7 +573,15 @@ TEST(function test_lookup_all_mixed(done) {
|
||||
else
|
||||
assert.fail('unexpected IP address');
|
||||
});
|
||||
}
|
||||
|
||||
validateResult(await dnsPromises.lookup(addresses.INET_HOST, { all: true }));
|
||||
|
||||
const req = dns.lookup(addresses.INET_HOST, {
|
||||
all: true
|
||||
}, function(err, ips) {
|
||||
assert.ifError(err);
|
||||
validateResult(ips);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -490,6 +590,10 @@ TEST(function test_lookup_all_mixed(done) {
|
||||
|
||||
|
||||
TEST(function test_lookupservice_invalid(done) {
|
||||
dnsPromises.lookupService('1.2.3.4', 80)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({ code: 'ENOTFOUND' }));
|
||||
|
||||
const req = dns.lookupService('1.2.3.4', 80, function(err, host, service) {
|
||||
assert(err instanceof Error);
|
||||
assert.strictEqual(err.code, 'ENOTFOUND');
|
||||
@ -503,6 +607,13 @@ TEST(function test_lookupservice_invalid(done) {
|
||||
|
||||
|
||||
TEST(function test_reverse_failure(done) {
|
||||
dnsPromises.reverse('203.0.113.0')
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({
|
||||
code: 'ENOTFOUND',
|
||||
hostname: '203.0.113.0'
|
||||
}));
|
||||
|
||||
// 203.0.113.0/24 are addresses reserved for (RFC) documentation use only
|
||||
const req = dns.reverse('203.0.113.0', function(err) {
|
||||
assert(err instanceof Error);
|
||||
@ -518,6 +629,13 @@ TEST(function test_reverse_failure(done) {
|
||||
|
||||
|
||||
TEST(function test_lookup_failure(done) {
|
||||
dnsPromises.lookup(addresses.INVALID_HOST)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({
|
||||
code: 'ENOTFOUND',
|
||||
hostname: addresses.INVALID_HOST
|
||||
}));
|
||||
|
||||
const req = dns.lookup(addresses.INVALID_HOST, (err) => {
|
||||
assert(err instanceof Error);
|
||||
assert.strictEqual(err.code, 'ENOTFOUND'); // Silly error code...
|
||||
@ -584,3 +702,7 @@ dns.lookup(addresses.INET6_HOST, 6, common.mustCall());
|
||||
dns.lookup(addresses.INET_HOST, {}, common.mustCall());
|
||||
dns.lookupService('0.0.0.0', '0', common.mustCall());
|
||||
dns.lookupService('0.0.0.0', 0, common.mustCall());
|
||||
(async function() {
|
||||
await dnsPromises.lookup(addresses.INET6_HOST, 6);
|
||||
await dnsPromises.lookup(addresses.INET_HOST, {});
|
||||
})();
|
||||
|
@ -23,8 +23,26 @@
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const dns = require('dns');
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
(async function() {
|
||||
let res;
|
||||
|
||||
res = await dnsPromises.lookup(null);
|
||||
assert.strictEqual(res.address, null);
|
||||
assert.strictEqual(res.family, 4);
|
||||
|
||||
res = await dnsPromises.lookup('127.0.0.1');
|
||||
assert.strictEqual(res.address, '127.0.0.1');
|
||||
assert.strictEqual(res.family, 4);
|
||||
|
||||
res = await dnsPromises.lookup('::1');
|
||||
assert.strictEqual(res.address, '::1');
|
||||
assert.strictEqual(res.family, 6);
|
||||
})();
|
||||
|
||||
// Try resolution without callback
|
||||
|
||||
@ -52,14 +70,18 @@ dns.lookup('::1', common.mustCall((error, result, addressType) => {
|
||||
// Try calling resolve with an unsupported type that's an object key
|
||||
'toString'
|
||||
].forEach((val) => {
|
||||
const err = {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: `The value "${val}" is invalid for option "rrtype"`
|
||||
};
|
||||
|
||||
common.expectsError(
|
||||
() => dns.resolve('www.google.com', val),
|
||||
{
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: `The value "${val}" is invalid for option "rrtype"`
|
||||
}
|
||||
err
|
||||
);
|
||||
|
||||
common.expectsError(() => dnsPromises.resolve('www.google.com', val), err);
|
||||
});
|
||||
|
||||
// Windows doesn't usually have an entry for localhost 127.0.0.1 in
|
||||
@ -70,4 +92,8 @@ if (!common.isWindows) {
|
||||
assert.ifError(error);
|
||||
assert.ok(Array.isArray(domains));
|
||||
}));
|
||||
|
||||
(async function() {
|
||||
assert.ok(Array.isArray(await dnsPromises.reverse('127.0.0.1')));
|
||||
})();
|
||||
}
|
||||
|
@ -3,17 +3,23 @@ const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const cares = process.binding('cares_wrap');
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
// Stub `getaddrinfo` to *always* error.
|
||||
cares.getaddrinfo = () => process.binding('uv').UV_ENOENT;
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookup(1, {});
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
type: TypeError,
|
||||
message: /^The "hostname" argument must be one of type string or falsy/
|
||||
});
|
||||
{
|
||||
const err = {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
type: TypeError,
|
||||
message: /^The "hostname" argument must be one of type string or falsy/
|
||||
};
|
||||
|
||||
common.expectsError(() => dns.lookup(1, {}), err);
|
||||
common.expectsError(() => dnsPromises.lookup(1, {}), err);
|
||||
}
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookup(false, 'cb');
|
||||
@ -29,29 +35,66 @@ common.expectsError(() => {
|
||||
type: TypeError
|
||||
});
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookup(false, {
|
||||
{
|
||||
const err = {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: 'The value "100" is invalid for option "hints"'
|
||||
};
|
||||
const options = {
|
||||
hints: 100,
|
||||
family: 0,
|
||||
all: false
|
||||
}, common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: 'The value "100" is invalid for option "hints"'
|
||||
});
|
||||
};
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookup(false, {
|
||||
common.expectsError(() => { dnsPromises.lookup(false, options); }, err);
|
||||
common.expectsError(() => {
|
||||
dns.lookup(false, options, common.mustNotCall());
|
||||
}, err);
|
||||
}
|
||||
|
||||
{
|
||||
const err = {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: 'The value "20" is invalid for option "family"'
|
||||
};
|
||||
const options = {
|
||||
hints: 0,
|
||||
family: 20,
|
||||
all: false
|
||||
}, common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: 'The value "20" is invalid for option "family"'
|
||||
});
|
||||
};
|
||||
|
||||
common.expectsError(() => { dnsPromises.lookup(false, options); }, err);
|
||||
common.expectsError(() => {
|
||||
dns.lookup(false, options, common.mustNotCall());
|
||||
}, err);
|
||||
}
|
||||
|
||||
(async function() {
|
||||
let res;
|
||||
|
||||
res = await dnsPromises.lookup(false, {
|
||||
hints: 0,
|
||||
family: 0,
|
||||
all: true
|
||||
});
|
||||
assert.deepStrictEqual(res, []);
|
||||
|
||||
res = await dnsPromises.lookup('127.0.0.1', {
|
||||
hints: 0,
|
||||
family: 4,
|
||||
all: true
|
||||
});
|
||||
assert.deepStrictEqual(res, [{ address: '127.0.0.1', family: 4 }]);
|
||||
|
||||
res = await dnsPromises.lookup('127.0.0.1', {
|
||||
hints: 0,
|
||||
family: 4,
|
||||
all: false
|
||||
});
|
||||
assert.deepStrictEqual(res, { address: '127.0.0.1', family: 4 });
|
||||
})();
|
||||
|
||||
dns.lookup(false, {
|
||||
hints: 0,
|
||||
|
@ -4,6 +4,9 @@ const dnstools = require('../common/dns');
|
||||
const dns = require('dns');
|
||||
const assert = require('assert');
|
||||
const dgram = require('dgram');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const server = dgram.createSocket('udp4');
|
||||
|
||||
@ -20,12 +23,20 @@ server.on('message', common.mustCall((msg, { address, port }) => {
|
||||
// Overwrite the # of answers with 2, which is incorrect.
|
||||
buf.writeUInt16LE(2, 6);
|
||||
server.send(buf, port, address);
|
||||
}));
|
||||
}, 2));
|
||||
|
||||
server.bind(0, common.mustCall(() => {
|
||||
server.bind(0, common.mustCall(async () => {
|
||||
const address = server.address();
|
||||
dns.setServers([`127.0.0.1:${address.port}`]);
|
||||
|
||||
dnsPromises.resolveAny('example.org')
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError({
|
||||
code: 'EBADRESP',
|
||||
syscall: 'queryAny',
|
||||
hostname: 'example.org'
|
||||
}));
|
||||
|
||||
dns.resolveAny('example.org', common.mustCall((err) => {
|
||||
assert.strictEqual(err.code, 'EBADRESP');
|
||||
assert.strictEqual(err.syscall, 'queryAny');
|
||||
|
@ -4,6 +4,9 @@ const dnstools = require('../common/dns');
|
||||
const dns = require('dns');
|
||||
const assert = require('assert');
|
||||
const dgram = require('dgram');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const answers = [
|
||||
{ type: 'A', address: '1.2.3.4', ttl: 123 },
|
||||
@ -36,18 +39,24 @@ server.on('message', common.mustCall((msg, { address, port }) => {
|
||||
questions: parsed.questions,
|
||||
answers: answers.map((answer) => Object.assign({ domain }, answer)),
|
||||
}), port, address);
|
||||
}));
|
||||
}, 2));
|
||||
|
||||
server.bind(0, common.mustCall(() => {
|
||||
server.bind(0, common.mustCall(async () => {
|
||||
const address = server.address();
|
||||
dns.setServers([`127.0.0.1:${address.port}`]);
|
||||
|
||||
validateResults(await dnsPromises.resolveAny('example.org'));
|
||||
|
||||
dns.resolveAny('example.org', common.mustCall((err, res) => {
|
||||
assert.ifError(err);
|
||||
// Compare copies with ttl removed, c-ares fiddles with that value.
|
||||
assert.deepStrictEqual(
|
||||
res.map((r) => Object.assign({}, r, { ttl: null })),
|
||||
answers.map((r) => Object.assign({}, r, { ttl: null })));
|
||||
validateResults(res);
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
function validateResults(res) {
|
||||
// Compare copies with ttl removed, c-ares fiddles with that value.
|
||||
assert.deepStrictEqual(
|
||||
res.map((r) => Object.assign({}, r, { ttl: null })),
|
||||
answers.map((r) => Object.assign({}, r, { ttl: null })));
|
||||
}
|
||||
|
@ -27,7 +27,18 @@ const common = require('../common');
|
||||
// Issue https://github.com/nodejs/node-v0.x-archive/issues/7070
|
||||
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
common.expectsError(
|
||||
() => dnsPromises.resolveNs([]), // bad name
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
type: TypeError,
|
||||
message: /^The "name" argument must be of type string/
|
||||
}
|
||||
);
|
||||
common.expectsError(
|
||||
() => dns.resolveNs([]), // bad name
|
||||
{
|
||||
|
@ -24,6 +24,9 @@ const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const dns = require('dns');
|
||||
const dnsPromises = dns.promises;
|
||||
|
||||
common.crashOnUnhandledRejection();
|
||||
|
||||
const existing = dns.getServers();
|
||||
assert(existing.length > 0);
|
||||
@ -149,7 +152,7 @@ common.expectsError(() => {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
type: TypeError,
|
||||
message: /^The "hostname" argument must be one of type string or falsy/
|
||||
}, 5);
|
||||
}, 10);
|
||||
|
||||
assert.throws(() => dns.lookup({}, common.mustNotCall()), errorReg);
|
||||
|
||||
@ -161,6 +164,12 @@ common.expectsError(() => {
|
||||
|
||||
assert.throws(() => dns.lookup(common.mustNotCall(), common.mustNotCall()),
|
||||
errorReg);
|
||||
|
||||
assert.throws(() => dnsPromises.lookup({}), errorReg);
|
||||
assert.throws(() => dnsPromises.lookup([]), errorReg);
|
||||
assert.throws(() => dnsPromises.lookup(true), errorReg);
|
||||
assert.throws(() => dnsPromises.lookup(1), errorReg);
|
||||
assert.throws(() => dnsPromises.lookup(common.mustNotCall()), errorReg);
|
||||
}
|
||||
|
||||
// dns.lookup should accept falsey values
|
||||
@ -171,30 +180,37 @@ common.expectsError(() => {
|
||||
assert.strictEqual(family, 4);
|
||||
};
|
||||
|
||||
dns.lookup('', common.mustCall(checkCallback));
|
||||
dns.lookup(null, common.mustCall(checkCallback));
|
||||
dns.lookup(undefined, common.mustCall(checkCallback));
|
||||
dns.lookup(0, common.mustCall(checkCallback));
|
||||
dns.lookup(NaN, common.mustCall(checkCallback));
|
||||
['', null, undefined, 0, NaN].forEach(async (value) => {
|
||||
const res = await dnsPromises.lookup(value);
|
||||
assert.deepStrictEqual(res, { address: null, family: 4 });
|
||||
dns.lookup(value, common.mustCall(checkCallback));
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that dns.lookup throws if hints does not represent a valid flag.
|
||||
* (dns.V4MAPPED | dns.ADDRCONFIG) + 1 is invalid because:
|
||||
* - it's different from dns.V4MAPPED and dns.ADDRCONFIG.
|
||||
* - it's different from them bitwise ored.
|
||||
* - it's different from 0.
|
||||
* - it's an odd number different than 1, and thus is invalid, because
|
||||
* flags are either === 1 or even.
|
||||
*/
|
||||
common.expectsError(() => {
|
||||
dns.lookup('nodejs.org', { hints: (dns.V4MAPPED | dns.ADDRCONFIG) + 1 },
|
||||
common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: /The value "\d+" is invalid for option "hints"/
|
||||
});
|
||||
{
|
||||
/*
|
||||
* Make sure that dns.lookup throws if hints does not represent a valid flag.
|
||||
* (dns.V4MAPPED | dns.ADDRCONFIG) + 1 is invalid because:
|
||||
* - it's different from dns.V4MAPPED and dns.ADDRCONFIG.
|
||||
* - it's different from them bitwise ored.
|
||||
* - it's different from 0.
|
||||
* - it's an odd number different than 1, and thus is invalid, because
|
||||
* flags are either === 1 or even.
|
||||
*/
|
||||
const hints = (dns.V4MAPPED | dns.ADDRCONFIG) + 1;
|
||||
const err = {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: /The value "\d+" is invalid for option "hints"/
|
||||
};
|
||||
|
||||
common.expectsError(() => {
|
||||
dnsPromises.lookup('nodejs.org', { hints });
|
||||
}, err);
|
||||
common.expectsError(() => {
|
||||
dns.lookup('nodejs.org', { hints }, common.mustNotCall());
|
||||
}, err);
|
||||
}
|
||||
|
||||
common.expectsError(() => dns.lookup('nodejs.org'), {
|
||||
code: 'ERR_INVALID_CALLBACK',
|
||||
@ -219,33 +235,57 @@ dns.lookup('', {
|
||||
hints: dns.ADDRCONFIG | dns.V4MAPPED
|
||||
}, common.mustCall());
|
||||
|
||||
common.expectsError(() => dns.lookupService('0.0.0.0'), {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
type: TypeError,
|
||||
message: 'The "host", "port", and "callback" arguments must be specified'
|
||||
});
|
||||
(async function() {
|
||||
await dnsPromises.lookup('', { family: 4, hints: 0 });
|
||||
await dnsPromises.lookup('', { family: 6, hints: dns.ADDRCONFIG });
|
||||
await dnsPromises.lookup('', { hints: dns.V4MAPPED });
|
||||
await dnsPromises.lookup('', { hints: dns.ADDRCONFIG | dns.V4MAPPED });
|
||||
})();
|
||||
|
||||
const invalidHost = 'fasdfdsaf';
|
||||
common.expectsError(() => {
|
||||
dns.lookupService(invalidHost, 0, common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: `The value "${invalidHost}" is invalid for option "host"`
|
||||
});
|
||||
{
|
||||
const err = {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
type: TypeError,
|
||||
message: 'The "host", "port", and "callback" arguments must be specified'
|
||||
};
|
||||
|
||||
common.expectsError(() => dns.lookupService('0.0.0.0'), err);
|
||||
err.message = 'The "host" and "port" arguments must be specified';
|
||||
common.expectsError(() => dnsPromises.lookupService('0.0.0.0'), err);
|
||||
}
|
||||
|
||||
{
|
||||
const invalidHost = 'fasdfdsaf';
|
||||
const err = {
|
||||
code: 'ERR_INVALID_OPT_VALUE',
|
||||
type: TypeError,
|
||||
message: `The value "${invalidHost}" is invalid for option "host"`
|
||||
};
|
||||
|
||||
common.expectsError(() => {
|
||||
dnsPromises.lookupService(invalidHost, 0);
|
||||
}, err);
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookupService(invalidHost, 0, common.mustNotCall());
|
||||
}, err);
|
||||
}
|
||||
|
||||
const portErr = (port) => {
|
||||
common.expectsError(
|
||||
() => {
|
||||
dns.lookupService('0.0.0.0', port, common.mustNotCall());
|
||||
},
|
||||
{
|
||||
code: 'ERR_SOCKET_BAD_PORT',
|
||||
message:
|
||||
`Port should be > 0 and < 65536. Received ${port}.`,
|
||||
type: RangeError
|
||||
}
|
||||
);
|
||||
const err = {
|
||||
code: 'ERR_SOCKET_BAD_PORT',
|
||||
message:
|
||||
`Port should be > 0 and < 65536. Received ${port}.`,
|
||||
type: RangeError
|
||||
};
|
||||
|
||||
common.expectsError(() => {
|
||||
dnsPromises.lookupService('0.0.0.0', port);
|
||||
}, err);
|
||||
|
||||
common.expectsError(() => {
|
||||
dns.lookupService('0.0.0.0', port, common.mustNotCall());
|
||||
}, err);
|
||||
};
|
||||
portErr(null);
|
||||
portErr(undefined);
|
||||
|
Loading…
x
Reference in New Issue
Block a user