mirror of
https://github.com/denoland/deno.git
synced 2024-11-23 15:16:54 -05:00
a77b2987bc
Fixes #19214. We were using the `idna` crate to implement our polyfill for `punycode.toASCII` and `punycode.toUnicode`. The `idna` crate is correct, and adheres to the IDNA2003/2008 spec, but it turns out `node`'s implementations don't really follow any spec! Instead, node splits the domain by `'.'` and punycode encodes/decodes each part. This means that node's implementations will happily work on codepoints that are disallowed by the IDNA specs, causing the error in #19214. While fixing this, I went ahead and matched the node behavior on all of the punycode functions and enabled node's punycode test in our `node_compat` suite.
1021 lines
27 KiB
TypeScript
1021 lines
27 KiB
TypeScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
// TODO(petamoriken): enable prefer-primordials for node polyfills
|
|
// deno-lint-ignore-file prefer-primordials
|
|
|
|
import { nextTick } from "ext:deno_node/_next_tick.ts";
|
|
import { customPromisifyArgs } from "ext:deno_node/internal/util.mjs";
|
|
import {
|
|
validateBoolean,
|
|
validateFunction,
|
|
validateNumber,
|
|
validateOneOf,
|
|
validateString,
|
|
} from "ext:deno_node/internal/validators.mjs";
|
|
import { isIP } from "ext:deno_node/internal/net.ts";
|
|
import {
|
|
emitInvalidHostnameWarning,
|
|
getDefaultResolver,
|
|
getDefaultVerbatim,
|
|
isFamily,
|
|
isLookupCallback,
|
|
isLookupOptions,
|
|
isResolveCallback,
|
|
Resolver as CallbackResolver,
|
|
setDefaultResolver,
|
|
setDefaultResultOrder,
|
|
validateHints,
|
|
} from "ext:deno_node/internal/dns/utils.ts";
|
|
import type {
|
|
AnyAaaaRecord,
|
|
AnyARecord,
|
|
AnyCnameRecord,
|
|
AnyMxRecord,
|
|
AnyNaptrRecord,
|
|
AnyNsRecord,
|
|
AnyPtrRecord,
|
|
AnyRecord,
|
|
AnySoaRecord,
|
|
AnySrvRecord,
|
|
AnyTxtRecord,
|
|
CaaRecord,
|
|
LookupAddress,
|
|
LookupAllOptions,
|
|
LookupOneOptions,
|
|
LookupOptions,
|
|
MxRecord,
|
|
NaptrRecord,
|
|
Records,
|
|
RecordWithTtl,
|
|
ResolveCallback,
|
|
ResolveOptions,
|
|
ResolverOptions,
|
|
ResolveWithTtlOptions,
|
|
SoaRecord,
|
|
SrvRecord,
|
|
} from "ext:deno_node/internal/dns/utils.ts";
|
|
import promisesBase from "ext:deno_node/internal/dns/promises.ts";
|
|
import type { ErrnoException } from "ext:deno_node/internal/errors.ts";
|
|
import {
|
|
dnsException,
|
|
ERR_INVALID_ARG_TYPE,
|
|
ERR_INVALID_ARG_VALUE,
|
|
} from "ext:deno_node/internal/errors.ts";
|
|
import {
|
|
AI_ADDRCONFIG as ADDRCONFIG,
|
|
AI_ALL as ALL,
|
|
AI_V4MAPPED as V4MAPPED,
|
|
} from "ext:deno_node/internal_binding/ares.ts";
|
|
import {
|
|
ChannelWrapQuery,
|
|
getaddrinfo,
|
|
GetAddrInfoReqWrap,
|
|
QueryReqWrap,
|
|
} from "ext:deno_node/internal_binding/cares_wrap.ts";
|
|
import { domainToASCII } from "ext:deno_node/internal/idna.ts";
|
|
import { notImplemented } from "ext:deno_node/_utils.ts";
|
|
|
|
function onlookup(
|
|
this: GetAddrInfoReqWrap,
|
|
err: number | null,
|
|
addresses: string[],
|
|
) {
|
|
if (err) {
|
|
return this.callback(dnsException(err, "getaddrinfo", this.hostname));
|
|
}
|
|
|
|
this.callback(null, addresses[0], this.family || isIP(addresses[0]));
|
|
}
|
|
|
|
function onlookupall(
|
|
this: GetAddrInfoReqWrap,
|
|
err: number | null,
|
|
addresses: string[],
|
|
) {
|
|
if (err) {
|
|
return this.callback(dnsException(err, "getaddrinfo", this.hostname));
|
|
}
|
|
|
|
const family = this.family;
|
|
const parsedAddresses = [];
|
|
|
|
for (let i = 0; i < addresses.length; i++) {
|
|
const addr = addresses[i];
|
|
parsedAddresses[i] = {
|
|
address: addr,
|
|
family: family || isIP(addr),
|
|
};
|
|
}
|
|
|
|
this.callback(null, parsedAddresses);
|
|
}
|
|
|
|
type LookupCallback = (
|
|
err: ErrnoException | null,
|
|
addressOrAddresses?: string | LookupAddress[] | null,
|
|
family?: number,
|
|
) => void;
|
|
|
|
const validFamilies = [0, 4, 6];
|
|
|
|
// Easy DNS A/AAAA look up
|
|
// lookup(hostname, [options,] callback)
|
|
export function lookup(
|
|
hostname: string,
|
|
family: number,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
address: string,
|
|
family: number,
|
|
) => void,
|
|
): GetAddrInfoReqWrap | Record<string, never>;
|
|
export function lookup(
|
|
hostname: string,
|
|
options: LookupOneOptions,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
address: string,
|
|
family: number,
|
|
) => void,
|
|
): GetAddrInfoReqWrap | Record<string, never>;
|
|
export function lookup(
|
|
hostname: string,
|
|
options: LookupAllOptions,
|
|
callback: (err: ErrnoException | null, addresses: LookupAddress[]) => void,
|
|
): GetAddrInfoReqWrap | Record<string, never>;
|
|
export function lookup(
|
|
hostname: string,
|
|
options: LookupOptions,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
address: string | LookupAddress[],
|
|
family: number,
|
|
) => void,
|
|
): GetAddrInfoReqWrap | Record<string, never>;
|
|
export function lookup(
|
|
hostname: string,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
address: string,
|
|
family: number,
|
|
) => void,
|
|
): GetAddrInfoReqWrap | Record<string, never>;
|
|
export function lookup(
|
|
hostname: string,
|
|
options: unknown,
|
|
callback?: unknown,
|
|
): GetAddrInfoReqWrap | Record<string, never> {
|
|
let hints = 0;
|
|
let family = 0;
|
|
let all = false;
|
|
let verbatim = getDefaultVerbatim();
|
|
|
|
// Parse arguments
|
|
if (hostname) {
|
|
validateString(hostname, "hostname");
|
|
}
|
|
|
|
if (isLookupCallback(options)) {
|
|
callback = options;
|
|
family = 0;
|
|
} else if (isFamily(options)) {
|
|
validateFunction(callback, "callback");
|
|
|
|
validateOneOf(options, "family", validFamilies);
|
|
family = options;
|
|
} else if (!isLookupOptions(options)) {
|
|
validateFunction(arguments.length === 2 ? options : callback, "callback");
|
|
|
|
throw new ERR_INVALID_ARG_TYPE("options", ["integer", "object"], options);
|
|
} else {
|
|
validateFunction(callback, "callback");
|
|
|
|
if (options?.hints != null) {
|
|
validateNumber(options.hints, "options.hints");
|
|
hints = options.hints >>> 0;
|
|
validateHints(hints);
|
|
}
|
|
|
|
if (options?.family != null) {
|
|
validateOneOf(options.family, "options.family", validFamilies);
|
|
family = options.family;
|
|
}
|
|
|
|
if (options?.all != null) {
|
|
validateBoolean(options.all, "options.all");
|
|
all = options.all;
|
|
}
|
|
|
|
if (options?.verbatim != null) {
|
|
validateBoolean(options.verbatim, "options.verbatim");
|
|
verbatim = options.verbatim;
|
|
}
|
|
}
|
|
|
|
if (!hostname) {
|
|
emitInvalidHostnameWarning(hostname);
|
|
|
|
if (all) {
|
|
nextTick(callback as LookupCallback, null, []);
|
|
} else {
|
|
nextTick(callback as LookupCallback, null, null, family === 6 ? 6 : 4);
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
const matchedFamily = isIP(hostname);
|
|
|
|
if (matchedFamily) {
|
|
if (all) {
|
|
nextTick(callback as LookupCallback, null, [
|
|
{ address: hostname, family: matchedFamily },
|
|
]);
|
|
} else {
|
|
nextTick(callback as LookupCallback, null, hostname, matchedFamily);
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
const req = new GetAddrInfoReqWrap();
|
|
req.callback = callback as LookupCallback;
|
|
req.family = family;
|
|
req.hostname = hostname;
|
|
req.oncomplete = all ? onlookupall : onlookup;
|
|
|
|
const err = getaddrinfo(
|
|
req,
|
|
domainToASCII(hostname),
|
|
family,
|
|
hints,
|
|
verbatim,
|
|
);
|
|
|
|
if (err) {
|
|
nextTick(
|
|
callback as LookupCallback,
|
|
dnsException(err, "getaddrinfo", hostname),
|
|
);
|
|
|
|
return {};
|
|
}
|
|
|
|
return req;
|
|
}
|
|
|
|
Object.defineProperty(lookup, customPromisifyArgs, {
|
|
value: ["address", "family"],
|
|
enumerable: false,
|
|
});
|
|
|
|
function onresolve(
|
|
this: QueryReqWrap,
|
|
err: number,
|
|
records: Records,
|
|
ttls?: number[],
|
|
) {
|
|
if (err) {
|
|
this.callback(dnsException(err, this.bindingName, this.hostname));
|
|
|
|
return;
|
|
}
|
|
|
|
const parsedRecords = ttls && this.ttl
|
|
? (records as string[]).map((address: string, index: number) => ({
|
|
address,
|
|
ttl: ttls[index],
|
|
}))
|
|
: records;
|
|
|
|
this.callback(null, parsedRecords);
|
|
}
|
|
|
|
function resolver(bindingName: keyof ChannelWrapQuery) {
|
|
function query(
|
|
this: Resolver,
|
|
name: string,
|
|
options: unknown,
|
|
callback?: unknown,
|
|
): QueryReqWrap {
|
|
if (isResolveCallback(options)) {
|
|
callback = options;
|
|
options = {};
|
|
}
|
|
|
|
validateString(name, "name");
|
|
validateFunction(callback, "callback");
|
|
|
|
const req = new QueryReqWrap();
|
|
req.bindingName = bindingName;
|
|
req.callback = callback as ResolveCallback;
|
|
req.hostname = name;
|
|
req.oncomplete = onresolve;
|
|
|
|
if (options && (options as ResolveOptions).ttl) {
|
|
notImplemented("dns.resolve* with ttl option");
|
|
}
|
|
|
|
req.ttl = !!(options && (options as ResolveOptions).ttl);
|
|
|
|
const err = this._handle[bindingName](req, domainToASCII(name));
|
|
|
|
if (err) {
|
|
throw dnsException(err, bindingName, name);
|
|
}
|
|
|
|
return req;
|
|
}
|
|
|
|
Object.defineProperty(query, "name", { value: bindingName });
|
|
|
|
return query;
|
|
}
|
|
|
|
const resolveMap = Object.create(null);
|
|
|
|
export class Resolver extends CallbackResolver {
|
|
constructor(options?: ResolverOptions) {
|
|
super(options);
|
|
}
|
|
|
|
// deno-lint-ignore no-explicit-any
|
|
[resolveMethod: string]: any;
|
|
}
|
|
|
|
Resolver.prototype.resolveAny = resolveMap.ANY = resolver("queryAny");
|
|
Resolver.prototype.resolve4 = resolveMap.A = resolver("queryA");
|
|
Resolver.prototype.resolve6 = resolveMap.AAAA = resolver("queryAaaa");
|
|
Resolver.prototype.resolveCaa = resolveMap.CAA = resolver("queryCaa");
|
|
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 = _resolve;
|
|
|
|
function _resolve(
|
|
this: Resolver,
|
|
hostname: string,
|
|
rrtype: unknown,
|
|
callback?: unknown,
|
|
): QueryReqWrap {
|
|
let resolver: Resolver;
|
|
|
|
if (typeof hostname !== "string") {
|
|
throw new ERR_INVALID_ARG_TYPE("name", "string", hostname);
|
|
}
|
|
|
|
if (typeof rrtype === "string") {
|
|
resolver = resolveMap[rrtype];
|
|
} else if (typeof rrtype === "function") {
|
|
resolver = resolveMap.A;
|
|
callback = rrtype;
|
|
} else {
|
|
throw new ERR_INVALID_ARG_TYPE("rrtype", "string", rrtype);
|
|
}
|
|
|
|
if (typeof resolver === "function") {
|
|
return Reflect.apply(resolver, this, [hostname, callback]);
|
|
}
|
|
|
|
throw new ERR_INVALID_ARG_VALUE("rrtype", rrtype);
|
|
}
|
|
|
|
/**
|
|
* Sets the IP address and port of servers to be used when performing DNS
|
|
* resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted
|
|
* addresses. If the port is the IANA default DNS port (53) it can be omitted.
|
|
*
|
|
* ```js
|
|
* dns.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 `dns.setServers()` method must not be called while a DNS query is in
|
|
* progress.
|
|
*
|
|
* The `setServers` method affects only `resolve`,`dns.resolve*()` and `reverse` (and specifically _not_ `lookup`).
|
|
*
|
|
* This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html).
|
|
* That is, if attempting to resolve with the first server provided results in a
|
|
* `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with
|
|
* subsequent servers provided. Fallback DNS servers will only be used if the
|
|
* earlier ones time out or result in some other error.
|
|
*
|
|
* @param servers array of `RFC 5952` formatted addresses
|
|
*/
|
|
export function setServers(servers: ReadonlyArray<string>) {
|
|
const resolver = new Resolver();
|
|
|
|
resolver.setServers(servers);
|
|
setDefaultResolver(resolver);
|
|
}
|
|
|
|
// The Node implementation uses `bindDefaultResolver` to set the follow methods
|
|
// on `module.exports` bound to the current `defaultResolver`. We don't have
|
|
// the same ability in ESM but can simulate this (at some cost) by explicitly
|
|
// exporting these methods which dynamically bind to the default resolver when
|
|
// called.
|
|
|
|
/**
|
|
* Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6),
|
|
* that are currently configured for DNS resolution. A string will include a port
|
|
* section if a custom port is used.
|
|
*
|
|
* ```js
|
|
* [
|
|
* '4.4.4.4',
|
|
* '2001:4860:4860::8888',
|
|
* '4.4.4.4:1053',
|
|
* '[2001:4860:4860::8888]:1053',
|
|
* ]
|
|
* ```
|
|
*/
|
|
export function getServers(): string[] {
|
|
return Resolver.prototype.getServers.bind(getDefaultResolver())();
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query).
|
|
* The `ret` argument passed to the `callback` function will be 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.
|
|
*
|
|
* Here is an example of the `ret` object passed to the callback:
|
|
*
|
|
* ```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 } ]
|
|
* ```
|
|
*
|
|
* DNS server operators may choose not to respond to `ANY` queries. It may be
|
|
* better to call individual methods like `resolve4`, `resolveMx`, and so on.
|
|
* For more details, see [RFC 8482](https://tools.ietf.org/html/rfc8482).
|
|
*/
|
|
export function resolveAny(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: AnyRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveAny(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveAny.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function will
|
|
* contain an array of IPv4 addresses (e.g. `['74.125.79.104', '74.125.79.105','74.125.79.106']`).
|
|
*
|
|
* @param hostname Host name to resolve.
|
|
*/
|
|
export function resolve4(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): void;
|
|
export function resolve4(
|
|
hostname: string,
|
|
options: ResolveWithTtlOptions,
|
|
callback: (err: ErrnoException | null, addresses: RecordWithTtl[]) => void,
|
|
): void;
|
|
export function resolve4(
|
|
hostname: string,
|
|
options: ResolveOptions,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
addresses: string[] | RecordWithTtl[],
|
|
) => void,
|
|
): void;
|
|
export function resolve4(
|
|
hostname: string,
|
|
options: unknown,
|
|
callback?: unknown,
|
|
) {
|
|
return Resolver.prototype.resolve4.bind(getDefaultResolver() as Resolver)(
|
|
hostname,
|
|
options,
|
|
callback,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve a IPv6 addresses (`AAAA` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function
|
|
* will contain an array of IPv6 addresses.
|
|
*
|
|
* @param hostname Host name to resolve.
|
|
*/
|
|
export function resolve6(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): void;
|
|
export function resolve6(
|
|
hostname: string,
|
|
options: ResolveWithTtlOptions,
|
|
callback: (err: ErrnoException | null, addresses: RecordWithTtl[]) => void,
|
|
): void;
|
|
export function resolve6(
|
|
hostname: string,
|
|
options: ResolveOptions,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
addresses: string[] | RecordWithTtl[],
|
|
) => void,
|
|
): void;
|
|
export function resolve6(
|
|
hostname: string,
|
|
options: unknown,
|
|
callback?: unknown,
|
|
) {
|
|
return Resolver.prototype.resolve6.bind(getDefaultResolver() as Resolver)(
|
|
hostname,
|
|
options,
|
|
callback,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve `CAA` records for the `hostname`. The
|
|
* `addresses` argument passed to the `callback` function will contain an array
|
|
* of certification authority authorization records available for the
|
|
* `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`).
|
|
*/
|
|
export function resolveCaa(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, records: CaaRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveCaa(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveCaa.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The
|
|
* `addresses` argument passed to the `callback` function will contain an array
|
|
* of canonical name records available for the `hostname`(e.g. `['bar.example.com']`).
|
|
*/
|
|
export function resolveCname(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveCname(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveCname.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve mail exchange records (`MX` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function will
|
|
* contain an array of objects containing both a `priority` and `exchange`
|
|
* property (e.g. `[{priority: 10, exchange: 'mx.example.com'}, ...]`).
|
|
*/
|
|
export function resolveMx(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: MxRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveMx(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveMx.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve name server records (`NS` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function will
|
|
* contain an array of name server records available for `hostname`
|
|
* (e.g. `['ns1.example.com', 'ns2.example.com']`).
|
|
*/
|
|
export function resolveNs(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveNs(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveNs.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve text queries (`TXT` records) for the
|
|
* `hostname`. The `records` argument passed to the `callback` function is 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.
|
|
*/
|
|
export function resolveTxt(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[][]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveTxt(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveTxt.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve service records (`SRV` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function will
|
|
* be an array of objects with the following properties:
|
|
*
|
|
* - `priority`
|
|
* - `weight`
|
|
* - `port`
|
|
* - `name`
|
|
*
|
|
* ```js
|
|
* {
|
|
* priority: 10,
|
|
* weight: 5,
|
|
* port: 21223,
|
|
* name: 'service.example.com'
|
|
* }
|
|
* ```
|
|
*/
|
|
export function resolveSrv(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveSrv(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveSrv.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve pointer records (`PTR` records) for the
|
|
* `hostname`. The `addresses` argument passed to the `callback` function will
|
|
* be an array of strings containing the reply records.
|
|
*/
|
|
export function resolvePtr(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolvePtr(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolvePtr.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve regular expression based records (`NAPTR`
|
|
* records) for the `hostname`. The `addresses` argument passed to the
|
|
* `callback` function will contain an array of objects with the following
|
|
* properties:
|
|
*
|
|
* - `flags`
|
|
* - `service`
|
|
* - `regexp`
|
|
* - `replacement`
|
|
* - `order`
|
|
* - `preference`
|
|
*
|
|
* ```js
|
|
* {
|
|
* flags: 's',
|
|
* service: 'SIP+D2U',
|
|
* regexp: '',
|
|
* replacement: '_sip._udp.example.com',
|
|
* order: 30,
|
|
* preference: 100
|
|
* }
|
|
* ```
|
|
*/
|
|
export function resolveNaptr(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: NaptrRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolveNaptr(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveNaptr.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve a start of authority record (`SOA` record) for
|
|
* the `hostname`. The `address` argument passed to the `callback` function will
|
|
* be an object with the following properties:
|
|
*
|
|
* - `nsname`
|
|
* - `hostmaster`
|
|
* - `serial`
|
|
* - `refresh`
|
|
* - `retry`
|
|
* - `expire`
|
|
* - `minttl`
|
|
*
|
|
* ```js
|
|
* {
|
|
* nsname: 'ns.example.com',
|
|
* hostmaster: 'root.example.com',
|
|
* serial: 2013101809,
|
|
* refresh: 10000,
|
|
* retry: 2400,
|
|
* expire: 604800,
|
|
* minttl: 3600
|
|
* }
|
|
* ```
|
|
*/
|
|
export function resolveSoa(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, address: SoaRecord) => void,
|
|
): QueryReqWrap;
|
|
export function resolveSoa(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.resolveSoa.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an
|
|
* array of host names.
|
|
*
|
|
* On error, `err` is an `Error` object, where `err.code` is
|
|
* one of the `DNS error codes`.
|
|
*/
|
|
export function reverse(
|
|
ip: string,
|
|
callback: (err: ErrnoException | null, hostnames: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function reverse(...args: unknown[]): QueryReqWrap {
|
|
return Resolver.prototype.reverse.bind(getDefaultResolver() as Resolver)(
|
|
...args,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array
|
|
* of the resource records. The `callback` function has arguments`(err, records)`.]
|
|
* When successful, `records` will be an array of resource
|
|
* records. The type and structure of individual results varies based on `rrtype`.
|
|
*
|
|
* On error, `err` is an `Error` object, where `err.code` is one of the DNS error codes.
|
|
*
|
|
* @param hostname Host name to resolve.
|
|
* @param [rrtype='A'] Resource record type.
|
|
*/
|
|
export function resolve(
|
|
hostname: string,
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "A",
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "AAAA",
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "ANY",
|
|
callback: (err: ErrnoException | null, addresses: AnyRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "CNAME",
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "MX",
|
|
callback: (err: ErrnoException | null, addresses: MxRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "NAPTR",
|
|
callback: (err: ErrnoException | null, addresses: NaptrRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "NS",
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "PTR",
|
|
callback: (err: ErrnoException | null, addresses: string[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "SOA",
|
|
callback: (err: ErrnoException | null, addresses: SoaRecord) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "SRV",
|
|
callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: "TXT",
|
|
callback: (err: ErrnoException | null, addresses: string[][]) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(
|
|
hostname: string,
|
|
rrtype: string,
|
|
callback: (
|
|
err: ErrnoException | null,
|
|
addresses:
|
|
| string[]
|
|
| MxRecord[]
|
|
| NaptrRecord[]
|
|
| SoaRecord
|
|
| SrvRecord[]
|
|
| string[][]
|
|
| AnyRecord[],
|
|
) => void,
|
|
): QueryReqWrap;
|
|
export function resolve(hostname: string, rrtype: unknown, callback?: unknown) {
|
|
return Resolver.prototype.resolve.bind(getDefaultResolver() as Resolver)(
|
|
hostname,
|
|
rrtype,
|
|
callback,
|
|
);
|
|
}
|
|
|
|
// ERROR CODES
|
|
export const NODATA = "ENODATA";
|
|
export const FORMERR = "EFORMERR";
|
|
export const SERVFAIL = "ESERVFAIL";
|
|
export const NOTFOUND = "ENOTFOUND";
|
|
export const NOTIMP = "ENOTIMP";
|
|
export const REFUSED = "EREFUSED";
|
|
export const BADQUERY = "EBADQUERY";
|
|
export const BADNAME = "EBADNAME";
|
|
export const BADFAMILY = "EBADFAMILY";
|
|
export const BADRESP = "EBADRESP";
|
|
export const CONNREFUSED = "ECONNREFUSED";
|
|
export const TIMEOUT = "ETIMEOUT";
|
|
export const EOF = "EOF";
|
|
export const FILE = "EFILE";
|
|
export const NOMEM = "ENOMEM";
|
|
export const DESTRUCTION = "EDESTRUCTION";
|
|
export const BADSTR = "EBADSTR";
|
|
export const BADFLAGS = "EBADFLAGS";
|
|
export const NONAME = "ENONAME";
|
|
export const BADHINTS = "EBADHINTS";
|
|
export const NOTINITIALIZED = "ENOTINITIALIZED";
|
|
export const LOADIPHLPAPI = "ELOADIPHLPAPI";
|
|
export const ADDRGETNETWORKPARAMS = "EADDRGETNETWORKPARAMS";
|
|
export const CANCELLED = "ECANCELLED";
|
|
|
|
const promises = {
|
|
...promisesBase,
|
|
setDefaultResultOrder,
|
|
setServers,
|
|
|
|
// ERROR CODES
|
|
NODATA,
|
|
FORMERR,
|
|
SERVFAIL,
|
|
NOTFOUND,
|
|
NOTIMP,
|
|
REFUSED,
|
|
BADQUERY,
|
|
BADNAME,
|
|
BADFAMILY,
|
|
BADRESP,
|
|
CONNREFUSED,
|
|
TIMEOUT,
|
|
EOF,
|
|
FILE,
|
|
NOMEM,
|
|
DESTRUCTION,
|
|
BADSTR,
|
|
BADFLAGS,
|
|
NONAME,
|
|
BADHINTS,
|
|
NOTINITIALIZED,
|
|
LOADIPHLPAPI,
|
|
ADDRGETNETWORKPARAMS,
|
|
CANCELLED,
|
|
};
|
|
|
|
export { ADDRCONFIG, ALL, promises, setDefaultResultOrder, V4MAPPED };
|
|
|
|
export type {
|
|
AnyAaaaRecord,
|
|
AnyARecord,
|
|
AnyCnameRecord,
|
|
AnyMxRecord,
|
|
AnyNaptrRecord,
|
|
AnyNsRecord,
|
|
AnyPtrRecord,
|
|
AnyRecord,
|
|
AnySoaRecord,
|
|
AnySrvRecord,
|
|
AnyTxtRecord,
|
|
CaaRecord,
|
|
LookupAddress,
|
|
LookupAllOptions,
|
|
LookupOneOptions,
|
|
LookupOptions,
|
|
MxRecord,
|
|
NaptrRecord,
|
|
Records,
|
|
RecordWithTtl,
|
|
ResolveCallback,
|
|
ResolveOptions,
|
|
ResolverOptions,
|
|
ResolveWithTtlOptions,
|
|
SoaRecord,
|
|
SrvRecord,
|
|
};
|
|
|
|
export default {
|
|
ADDRCONFIG,
|
|
ALL,
|
|
V4MAPPED,
|
|
lookup,
|
|
getServers,
|
|
resolveAny,
|
|
resolve4,
|
|
resolve6,
|
|
resolveCaa,
|
|
resolveCname,
|
|
resolveMx,
|
|
resolveNs,
|
|
resolveTxt,
|
|
resolveSrv,
|
|
resolvePtr,
|
|
resolveNaptr,
|
|
resolveSoa,
|
|
resolve,
|
|
Resolver,
|
|
reverse,
|
|
setServers,
|
|
setDefaultResultOrder,
|
|
promises,
|
|
NODATA,
|
|
FORMERR,
|
|
SERVFAIL,
|
|
NOTFOUND,
|
|
NOTIMP,
|
|
REFUSED,
|
|
BADQUERY,
|
|
BADNAME,
|
|
BADFAMILY,
|
|
BADRESP,
|
|
CONNREFUSED,
|
|
TIMEOUT,
|
|
EOF,
|
|
FILE,
|
|
NOMEM,
|
|
DESTRUCTION,
|
|
BADSTR,
|
|
BADFLAGS,
|
|
NONAME,
|
|
BADHINTS,
|
|
NOTINITIALIZED,
|
|
LOADIPHLPAPI,
|
|
ADDRGETNETWORKPARAMS,
|
|
CANCELLED,
|
|
};
|