DNS#

穩定性:2 - 穩定

原始碼: lib/dns.js

node:dns 模組啟用了名稱解析。例如,用它來查詢主機的 IP 地址。

雖然它以域名系統 (DNS)命名,但它並不總是使用 DNS 協議進行查詢。dns.lookup() 使用作業系統設施來執行名稱解析。它可能不需要執行任何網路通訊。要像同一系統上的其他應用程式一樣執行名稱解析,請使用 dns.lookup()

import dns from 'node:dns';

dns.lookup('example.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6const dns = require('node:dns');

dns.lookup('example.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

node:dns 模組中的所有其他函式都會連線到實際的 DNS 伺服器來執行名稱解析。它們將始終使用網路來執行 DNS 查詢。這些函式不使用與 dns.lookup() 相同的配置檔案集(例如 /etc/hosts)。使用這些函式可以始終執行 DNS 查詢,繞過其他名稱解析設施。

import dns from 'node:dns';

dns.resolve4('archive.org', (err, addresses) => {
  if (err) throw err;

  console.log(`addresses: ${JSON.stringify(addresses)}`);

  addresses.forEach((a) => {
    dns.reverse(a, (err, hostnames) => {
      if (err) {
        throw err;
      }
      console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`);
    });
  });
});const dns = require('node:dns');

dns.resolve4('archive.org', (err, addresses) => {
  if (err) throw err;

  console.log(`addresses: ${JSON.stringify(addresses)}`);

  addresses.forEach((a) => {
    dns.reverse(a, (err, hostnames) => {
      if (err) {
        throw err;
      }
      console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`);
    });
  });
});

有關更多資訊,請參閱實現注意事項部分

類:dns.Resolver#

用於 DNS 請求的獨立解析器。

建立一個新的解析器會使用預設的伺服器設定。使用 resolver.setServers() 為一個解析器設定伺服器不會影響其他解析器。

import { Resolver } from 'node:dns';
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', (err, addresses) => {
  // ...
});const { Resolver } = require('node:dns');
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', (err, addresses) => {
  // ...
});

node:dns 模組中的以下方法可用

Resolver([options])#

建立一個新的解析器。

  • options <Object>
    • timeout <integer> 查詢超時(以毫秒為單位),或 -1 使用預設超時。
    • tries <integer> 解析器在放棄之前將嘗試聯絡每個名稱伺服器的次數。預設值:4
    • maxTimeout <integer> 最大重試超時時間,以毫秒為單位。預設值: 0,停用。

resolver.cancel()#

取消此解析器發出的所有未完成的 DNS 查詢。相應的回撥函式將以一個帶有程式碼 ECANCELLED 的錯誤被呼叫。

resolver.setLocalAddress([ipv4][, ipv6])#

  • ipv4 <string> IPv4 地址的字串表示形式。預設值: '0.0.0.0'
  • ipv6 <string> IPv6 地址的字串表示形式。預設值: '::0'

解析器例項將從指定的 IP 地址傳送其請求。這允許程式在多宿主系統上指定出站介面。

如果未指定 v4 或 v6 地址,則會將其設定為預設值,作業系統將自動選擇一個本地地址。

解析器在向 IPv4 DNS 伺服器發出請求時將使用 v4 本地地址,在向 IPv6 DNS 伺服器發出請求時將使用 v6 本地地址。解析請求的 rrtype 對使用的本地地址沒有影響。

dns.getServers()#

返回一個 IP 地址字串陣列,根據 RFC 5952 格式化,這些地址當前已配置用於 DNS 解析。如果使用了自定義埠,字串將包含一個埠部分。

[
  '8.8.8.8',
  '2001:4860:4860::8888',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
] 

dns.lookup(hostname[, options], callback)#

  • hostname <string>
  • options <integer> | <Object>
    • family <integer> | <string> 記錄族。必須是 460。出於向後相容的原因,'IPv4''IPv6' 分別被解釋為 46。值 0 表示返回 IPv4 或 IPv6 地址。如果值 0{ all: true }(見下文)一起使用,則會返回 IPv4 和 IPv6 地址中的一個或兩個,具體取決於系統的 DNS 解析器。預設值: 0
    • hints <number> 一個或多個支援的 getaddrinfo 標誌。可以透過按位運算它們的值來傳遞多個標誌。
    • all <boolean> 當為 true 時,回撥函式返回一個包含所有已解析地址的陣列。否則,返回單個地址。預設值: false
    • order <string> 當為 verbatim 時,返回的已解析地址是未排序的。當為 ipv4first 時,已解析地址按 IPv4 地址在前、IPv6 地址在後的順序排序。當為 ipv6first 時,已解析地址按 IPv6 地址在前、IPv4 地址在後的順序排序。預設值: verbatim(地址不重新排序)。預設值可透過 dns.setDefaultResultOrder()--dns-result-order 進行配置。
    • verbatim <boolean> 當為 true 時,回撥函式接收到的 IPv4 和 IPv6 地址的順序與 DNS 解析器返回的順序相同。當為 false 時,IPv4 地址會排在 IPv6 地址之前。此選項將被 order 棄用。當兩者都指定時,order 具有更高的優先順序。新程式碼應僅使用 order預設值: true(地址不重新排序)。預設值可透過 dns.setDefaultResultOrder()--dns-result-order 進行配置。
  • callback <Function>
    • err <Error>
    • address <string> IPv4 或 IPv6 地址的字串表示形式。
    • family <integer> 46,表示 address 的族,如果地址不是 IPv4 或 IPv6 地址,則為 00 很可能表示作業系統使用的名稱解析服務中存在錯誤。

將主機名(例如 'nodejs.org')解析為找到的第一個 A (IPv4) 或 AAAA (IPv6) 記錄。所有 option 屬性都是可選的。如果 options 是一個整數,那麼它必須是 46——如果未提供 options,則如果找到,將返回 IPv4 或 IPv6 地址,或兩者都返回。

all 選項設定為 true 時,callback 的引數變為 (err, addresses),其中 addresses 是一個物件陣列,每個物件都有 addressfamily 屬性。

出錯時,err 是一個 Error 物件,其中 err.code 是錯誤程式碼。請記住,err.code 將被設定為 'ENOTFOUND',不僅在主機名不存在時,也在查詢因其他原因(如沒有可用的檔案描述符)失敗時。

dns.lookup() 不一定與 DNS 協議有任何關係。該實現使用作業系統設施,可以將名稱與地址關聯,反之亦然。這種實現可能對任何 Node.js 程式的行為產生細微但重要的影響。在使用 dns.lookup() 之前,請花一些時間查閱實現注意事項部分

用法示例:

import dns from 'node:dns';
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.org', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, family));
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

// When options.all is true, the result will be an Array.
options.all = true;
dns.lookup('example.org', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]const dns = require('node:dns');
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.org', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, family));
// address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6

// When options.all is true, the result will be an Array.
options.all = true;
dns.lookup('example.org', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]

如果此方法以其 util.promisify() 化的版本被呼叫,並且 all 未設定為 true,它將返回一個 Promise,該 Promise 解析為一個具有 addressfamily 屬性的 Object

支援的 getaddrinfo 標誌#

以下標誌可以作為提示傳遞給 dns.lookup()

  • dns.ADDRCONFIG:將返回的地址型別限制為系統上配置的非環回地址的型別。例如,僅噹噹前系統至少配置了一個 IPv4 地址時,才會返回 IPv4 地址。
  • dns.V4MAPPED:如果指定了 IPv6 族,但未找到 IPv6 地址,則返回 IPv4 對映的 IPv6 地址。某些作業系統(例如 FreeBSD 10.1)不支援此功能。
  • dns.ALL:如果指定了 dns.V4MAPPED,則返回已解析的 IPv6 地址以及 IPv4 對映的 IPv6 地址。

dns.lookupService(address, port, callback)#

使用作業系統的底層 getnameinfo 實現,將給定的 addressport 解析為主機名和服務。

如果 address 不是一個有效的 IP 地址,將丟擲 TypeErrorport 將被強制轉換為一個數字。如果它不是一個合法的埠,將丟擲 TypeError

出錯時,err 是一個 Error 物件,其中 err.code 是錯誤程式碼。

import dns from 'node:dns';
dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
  console.log(hostname, service);
  // Prints: localhost ssh
});const dns = require('node:dns');
dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
  console.log(hostname, service);
  // Prints: localhost ssh
});

如果此方法以其 util.promisify() 化的版本被呼叫,它將返回一個 Promise,該 Promise 解析為一個具有 hostnameservice 屬性的 Object

dns.resolve(hostname[, rrtype], callback)#

使用 DNS 協議將主機名(例如 'nodejs.org')解析為資源記錄陣列。callback 函式的引數為 (err, records)。成功時,records 將是一個資源記錄陣列。單個結果的型別和結構根據 rrtype 而變化。

rrtyperecords 包含結果型別快捷方法
'A'IPv4 地址(預設)<string>dns.resolve4()
'AAAA'IPv6 地址<string>dns.resolve6()
'ANY'任何記錄<Object>dns.resolveAny()
'CAA'CA 授權記錄<Object>dns.resolveCaa()
'CNAME'規範名稱記錄<string>dns.resolveCname()
'MX'郵件交換記錄<Object>dns.resolveMx()
'NAPTR'名稱權威指標記錄<Object>dns.resolveNaptr()
'NS'名稱伺服器記錄<string>dns.resolveNs()
'PTR'指標記錄<string>dns.resolvePtr()
'SOA'起始授權機構記錄<Object>dns.resolveSoa()
'SRV'服務記錄<Object>dns.resolveSrv()
'TLSA'證書關聯<Object>dns.resolveTlsa()
'TXT'文字記錄<string[]>dns.resolveTxt()

出錯時,err 是一個 Error 物件,其中 err.codeDNS 錯誤程式碼之一。

dns.resolve4(hostname[, options], callback)#

  • hostname <string> 要解析的主機名。
  • options <Object>
    • ttl <boolean> 檢索每條記錄的生存時間(TTL)值。當為 true 時,回撥函式接收一個 { address: '1.2.3.4', ttl: 60 } 物件陣列,而不是字串陣列,其中 TTL 以秒為單位表示。
  • callback <Function>

使用 DNS 協議解析 hostname 的 IPv4 地址(A 記錄)。傳遞給 callback 函式的 addresses 引數將包含一個 IPv4 地址陣列(例如 ['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dns.resolve6(hostname[, options], callback)#

  • hostname <string> 要解析的主機名。
  • options <Object>
    • ttl <boolean> 檢索每條記錄的生存時間(TTL)值。當為 true 時,回撥函式接收一個 { address: '0:1:2:3:4:5:6:7', ttl: 60 } 物件陣列,而不是字串陣列,其中 TTL 以秒為單位表示。
  • callback <Function>

使用 DNS 協議解析 hostname 的 IPv6 地址(AAAA 記錄)。傳遞給 callback 函式的 addresses 引數將包含一個 IPv6 地址陣列。

dns.resolveAny(hostname, callback)#

使用 DNS 協議解析所有記錄(也稱為 ANY* 查詢)。傳遞給 callback 函式的 ret 引數將是一個包含各種型別記錄的陣列。每個物件都有一個 type 屬性,指示當前記錄的型別。並且根據 type,物件上還會存在其他屬性。

型別屬性
'A'address/ttl
'AAAA'address/ttl
'CNAME'value
'MX'請參閱 dns.resolveMx()
'NAPTR'請參閱 dns.resolveNaptr()
'NS'value
'PTR'value
'SOA'請參閱 dns.resolveSoa()
'SRV'請參閱 dns.resolveSrv()
'TLSA'請參閱 dns.resolveTlsa()
'TXT'這種型別的記錄包含一個名為 entries 的陣列屬性,它引用了 dns.resolveTxt(),例如 { entries: ['...'], type: 'TXT' }

以下是傳遞給回撥的 ret 物件的示例:

[ { 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 伺服器操作員可能選擇不響應 ANY 查詢。最好呼叫諸如 dns.resolve4()dns.resolveMx() 等單個方法。有關更多詳細資訊,請參閱 RFC 8482

dns.resolveCname(hostname, callback)#

使用 DNS 協議解析 hostnameCNAME 記錄。傳遞給 callback 函式的 addresses 引數將包含一個可用於 hostname 的規範名稱記錄陣列(例如 ['bar.example.com'])。

dns.resolveCaa(hostname, callback)#

使用 DNS 協議解析 hostnameCAA 記錄。傳遞給 callback 函式的 addresses 引數將包含一個可用於 hostname 的證書頒發機構授權記錄陣列(例如 [{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}])。

dns.resolveMx(hostname, callback)#

使用 DNS 協議解析 hostname 的郵件交換記錄(MX 記錄)。傳遞給 callback 函式的 addresses 引數將包含一個物件陣列,每個物件都包含 priorityexchange 屬性(例如 [{priority: 10, exchange: 'mx.example.com'}, ...])。

dns.resolveNaptr(hostname, callback)#

使用 DNS 協議解析 hostname 的基於正則表示式的記錄(NAPTR 記錄)。傳遞給 callback 函式的 addresses 引數將包含一個具有以下屬性的物件陣列:

  • flags
  • service
  • regexp
  • replacement
  • order
  • preference
{
  flags: 's',
  service: 'SIP+D2U',
  regexp: '',
  replacement: '_sip._udp.example.com',
  order: 30,
  preference: 100
} 

dns.resolveNs(hostname, callback)#

使用 DNS 協議解析 hostname 的名稱伺服器記錄(NS 記錄)。傳遞給 callback 函式的 addresses 引數將包含一個可用於 hostname 的名稱伺服器記錄陣列(例如 ['ns1.example.com', 'ns2.example.com'])。

dns.resolvePtr(hostname, callback)#

使用 DNS 協議解析 hostname 的指標記錄(PTR 記錄)。傳遞給 callback 函式的 addresses 引數將是一個包含應答記錄的字串陣列。

dns.resolveSoa(hostname, callback)#

使用 DNS 協議解析 hostname 的起始授權機構記錄(SOA 記錄)。傳遞給 callback 函式的 address 引數將是一個具有以下屬性的物件:

  • nsname
  • hostmaster
  • serial
  • refresh
  • retry
  • expire
  • minttl
{
  nsname: 'ns.example.com',
  hostmaster: 'root.example.com',
  serial: 2013101809,
  refresh: 10000,
  retry: 2400,
  expire: 604800,
  minttl: 3600
} 

dns.resolveSrv(hostname, callback)#

使用 DNS 協議解析 hostname 的服務記錄(SRV 記錄)。傳遞給 callback 函式的 addresses 引數將是一個具有以下屬性的物件陣列:

  • priority
  • weight
  • port
  • name
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dns.resolveTlsa(hostname, callback)#

使用 DNS 協議解析 hostname 的證書關聯記錄(TLSA 記錄)。傳遞給 callback 函式的 records 引數是一個具有以下屬性的物件陣列:

  • certUsage
  • selector
  • match
  • data
{
  certUsage: 3,
  selector: 1,
  match: 1,
  data: [ArrayBuffer]
} 

dns.resolveTxt(hostname, callback)#

使用 DNS 協議解析 hostname 的文字查詢(TXT 記錄)。傳遞給 callback 函式的 records 引數是一個二維陣列,其中包含 hostname 可用的文字記錄(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每個子陣列包含一條記錄的 TXT 塊。根據用例,這些塊可以連線在一起或分開處理。

dns.reverse(ip, callback)#

執行反向 DNS 查詢,將 IPv4 或 IPv6 地址解析為主機名陣列。

出錯時,err 是一個 Error 物件,其中 err.codeDNS 錯誤程式碼之一。

dns.setDefaultResultOrder(order)#

  • order <string> 必須是 'ipv4first''ipv6first''verbatim'

設定 dns.lookup()dnsPromises.lookup()order 的預設值。該值可以是:

  • ipv4first:將預設 order 設定為 ipv4first
  • ipv6first:將預設 order 設定為 ipv6first
  • verbatim:將預設 order 設定為 verbatim

預設值為 verbatimdns.setDefaultResultOrder() 的優先順序高於 --dns-result-order。在使用 工作執行緒時,主執行緒的 dns.setDefaultResultOrder() 不會影響工作執行緒中的預設 dns 順序。

dns.getDefaultResultOrder()#

獲取 dns.lookup()dnsPromises.lookup()order 的預設值。該值可以是:

  • ipv4first:對於預設 orderipv4first
  • ipv6first:對於預設 orderipv6first
  • verbatim:對於預設 orderverbatim

dns.setServers(servers)#

設定執行 DNS 解析時要使用的伺服器的 IP 地址和埠。servers 引數是一個 RFC 5952 格式化地址的陣列。如果埠是 IANA 預設的 DNS 埠 (53),則可以省略。

dns.setServers([
  '8.8.8.8',
  '[2001:4860:4860::8888]',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
]); 

如果提供了無效地址,將丟擲錯誤。

在 DNS 查詢進行中時,不得呼叫 dns.setServers() 方法。

dns.setServers() 方法僅影響 dns.resolve()dns.resolve*()dns.reverse()(並且特別地影響 dns.lookup())。

此方法的工作方式很像 resolve.conf。也就是說,如果嘗試使用提供的第一個伺服器解析導致 NOTFOUND 錯誤,resolve() 方法將不會嘗試使用後續提供的伺服器進行解析。只有當較早的伺服器超時或導致其他錯誤時,才會使用備用 DNS 伺服器。

DNS promises API#

dns.promises API 提供了一組替代的非同步 DNS 方法,它們返回 Promise 物件而不是使用回撥。該 API 可透過 require('node:dns').promisesrequire('node:dns/promises') 訪問。

類:dnsPromises.Resolver#

用於 DNS 請求的獨立解析器。

建立一個新的解析器會使用預設的伺服器設定。使用 resolver.setServers() 為一個解析器設定伺服器不會影響其他解析器。

import { Resolver } from 'node: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.
const addresses = await resolver.resolve4('example.org');const { Resolver } = require('node: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');
})();

dnsPromises API 中的以下方法可用

resolver.cancel()#

取消此解析器發出的所有未完成的 DNS 查詢。相應的 Promise 將被一個帶有程式碼 ECANCELLED 的錯誤拒絕。

dnsPromises.getServers()#

返回一個 IP 地址字串陣列,根據 RFC 5952 格式化,這些地址當前已配置用於 DNS 解析。如果使用了自定義埠,字串將包含一個埠部分。

[
  '8.8.8.8',
  '2001:4860:4860::8888',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
] 

dnsPromises.lookup(hostname[, options])#

  • hostname <string>
  • options <integer> | <Object>
    • family <integer> 記錄族。必須是 460。值 0 表示返回 IPv4 或 IPv6 地址。如果值 0{ all: true }(見下文)一起使用,則會返回 IPv4 和 IPv6 地址中的一個或兩個,具體取決於系統的 DNS 解析器。預設值: 0
    • hints <number> 一個或多個支援的 getaddrinfo 標誌。可以透過按位運算它們的值來傳遞多個標誌。
    • all <boolean> 當為 true 時,Promise 解析為一個包含所有地址的陣列。否則,返回單個地址。預設值: false
    • order <string> 當為 verbatim 時,Promise 解析的結果中,IPv4 和 IPv6 地址的順序與 DNS 解析器返回的順序相同。當為 ipv4first 時,IPv4 地址會排在 IPv6 地址之前。當為 ipv6first 時,IPv6 地址會排在 IPv4 地址之前。預設值: verbatim(地址不重新排序)。預設值可透過 dns.setDefaultResultOrder()--dns-result-order 進行配置。新程式碼應使用 { order: 'verbatim' }
    • verbatim <boolean> 當為 true 時,Promise 解析的結果中,IPv4 和 IPv6 地址的順序與 DNS 解析器返回的順序相同。當為 false 時,IPv4 地址會排在 IPv6 地址之前。此選項將被 order 棄用。當兩者都指定時,order 具有更高的優先順序。新程式碼應僅使用 order預設值: 當前為 false(地址被重新排序),但這在不久的將來預計會改變。預設值可透過 dns.setDefaultResultOrder()--dns-result-order 進行配置。

將主機名(例如 'nodejs.org')解析為找到的第一個 A (IPv4) 或 AAAA (IPv6) 記錄。所有 option 屬性都是可選的。如果 options 是一個整數,那麼它必須是 46——如果未提供 options,則如果找到,將返回 IPv4 或 IPv6 地址,或兩者都返回。

all 選項設定為 true 時,Promise 解析的結果中,addresses 是一個物件陣列,每個物件都有 addressfamily 屬性。

出錯時,Promise 會被一個 Error 物件拒絕,其中 err.code 是錯誤程式碼。請記住,err.code 將被設定為 'ENOTFOUND',不僅在主機名不存在時,也在查詢因其他原因(如沒有可用的檔案描述符)失敗時。

dnsPromises.lookup() 不一定與 DNS 協議有任何關係。該實現使用作業系統設施,可以將名稱與地址關聯,反之亦然。這種實現可能對任何 Node.js 程式的行為產生細微但重要的影響。在使用 dnsPromises.lookup() 之前,請花一些時間查閱實現注意事項部分

用法示例:

import dns from 'node:dns';
const dnsPromises = dns.promises;
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};

await dnsPromises.lookup('example.org', options).then((result) => {
  console.log('address: %j family: IPv%s', result.address, result.family);
  // address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6
});

// When options.all is true, the result will be an Array.
options.all = true;
await dnsPromises.lookup('example.org', options).then((result) => {
  console.log('addresses: %j', result);
  // addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]
});const dns = require('node:dns');
const dnsPromises = dns.promises;
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};

dnsPromises.lookup('example.org', options).then((result) => {
  console.log('address: %j family: IPv%s', result.address, result.family);
  // address: "2606:2800:21f:cb07:6820:80da:af6b:8b2c" family: IPv6
});

// When options.all is true, the result will be an Array.
options.all = true;
dnsPromises.lookup('example.org', options).then((result) => {
  console.log('addresses: %j', result);
  // addresses: [{"address":"2606:2800:21f:cb07:6820:80da:af6b:8b2c","family":6}]
});

dnsPromises.lookupService(address, port)#

使用作業系統的底層 getnameinfo 實現,將給定的 addressport 解析為主機名和服務。

如果 address 不是一個有效的 IP 地址,將丟擲 TypeErrorport 將被強制轉換為一個數字。如果它不是一個合法的埠,將丟擲 TypeError

出錯時,Promise 會被一個 Error 物件拒絕,其中 err.code 是錯誤程式碼。

import dnsPromises from 'node:dns/promises';
const result = await dnsPromises.lookupService('127.0.0.1', 22);

console.log(result.hostname, result.service); // Prints: localhost sshconst dnsPromises = require('node:dns').promises;
dnsPromises.lookupService('127.0.0.1', 22).then((result) => {
  console.log(result.hostname, result.service);
  // Prints: localhost ssh
});

dnsPromises.resolve(hostname[, rrtype])#

  • hostname <string> 要解析的主機名。
  • rrtype <string> 資源記錄型別。預設值: 'A'

使用 DNS 協議將主機名(例如 'nodejs.org')解析為資源記錄陣列。成功時,Promise 解析為一個資源記錄陣列。單個結果的型別和結構根據 rrtype 而變化。

rrtyperecords 包含結果型別快捷方法
'A'IPv4 地址(預設)<string>dnsPromises.resolve4()
'AAAA'IPv6 地址<string>dnsPromises.resolve6()
'ANY'任何記錄<Object>dnsPromises.resolveAny()
'CAA'CA 授權記錄<Object>dnsPromises.resolveCaa()
'CNAME'規範名稱記錄<string>dnsPromises.resolveCname()
'MX'郵件交換記錄<Object>dnsPromises.resolveMx()
'NAPTR'名稱權威指標記錄<Object>dnsPromises.resolveNaptr()
'NS'名稱伺服器記錄<string>dnsPromises.resolveNs()
'PTR'指標記錄<string>dnsPromises.resolvePtr()
'SOA'起始授權機構記錄<Object>dnsPromises.resolveSoa()
'SRV'服務記錄<Object>dnsPromises.resolveSrv()
'TLSA'證書關聯<Object>dnsPromises.resolveTlsa()
'TXT'文字記錄<string[]>dnsPromises.resolveTxt()

出錯時,Promise 會被一個 Error 物件拒絕,其中 err.codeDNS 錯誤程式碼之一。

dnsPromises.resolve4(hostname[, options])#

  • hostname <string> 要解析的主機名。
  • options <Object>
    • ttl <boolean> 檢索每條記錄的生存時間(TTL)值。當為 true 時,Promise 解析為一個 { address: '1.2.3.4', ttl: 60 } 物件陣列,而不是字串陣列,其中 TTL 以秒為單位表示。

使用 DNS 協議解析 hostname 的 IPv4 地址(A 記錄)。成功時,Promise 解析為一個 IPv4 地址陣列(例如 ['74.125.79.104', '74.125.79.105', '74.125.79.106'])。

dnsPromises.resolve6(hostname[, options])#

  • hostname <string> 要解析的主機名。
  • options <Object>
    • ttl <boolean> 檢索每條記錄的生存時間(TTL)值。當為 true 時,Promise 解析為一個 { address: '0:1:2:3:4:5:6:7', ttl: 60 } 物件陣列,而不是字串陣列,其中 TTL 以秒為單位表示。

使用 DNS 協議解析 hostname 的 IPv6 地址(AAAA 記錄)。成功時,Promise 解析為一個 IPv6 地址陣列。

dnsPromises.resolveAny(hostname)#

使用 DNS 協議解析所有記錄(也稱為 ANY* 查詢)。成功時,Promise 解析為一個包含各種型別記錄的陣列。每個物件都有一個 type 屬性,指示當前記錄的型別。並且根據 type,物件上還會存在其他屬性。

型別屬性
'A'address/ttl
'AAAA'address/ttl
'CNAME'value
'MX'請參閱 dnsPromises.resolveMx()
'NAPTR'請參閱 dnsPromises.resolveNaptr()
'NS'value
'PTR'value
'SOA'請參閱 dnsPromises.resolveSoa()
'SRV'請參閱 dnsPromises.resolveSrv()
'TLSA'請參閱 dnsPromises.resolveTlsa()
'TXT'這種型別的記錄包含一個名為 entries 的陣列屬性,它引用了 dnsPromises.resolveTxt(),例如 { entries: ['...'], type: 'TXT' }

以下是結果物件的示例:

[ { 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.resolveCaa(hostname)#

使用 DNS 協議解析 hostnameCAA 記錄。成功時,Promise 解析為一個物件陣列,其中包含可用於 hostname 的證書頒發機構授權記錄(例如 [{critical: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: 'pki.example.com'}])。

dnsPromises.resolveCname(hostname)#

使用 DNS 協議解析 hostnameCNAME 記錄。成功時,Promise 解析為一個可用於 hostname 的規範名稱記錄陣列(例如 ['bar.example.com'])。

dnsPromises.resolveMx(hostname)#

使用 DNS 協議解析 hostname 的郵件交換記錄(MX 記錄)。成功時,Promise 解析為一個物件陣列,每個物件都包含 priorityexchange 屬性(例如 [{priority: 10, exchange: 'mx.example.com'}, ...])。

dnsPromises.resolveNaptr(hostname)#

使用 DNS 協議解析 hostname 的基於正則表示式的記錄(NAPTR 記錄)。成功時,Promise 解析為一個具有以下屬性的物件陣列:

  • flags
  • service
  • regexp
  • replacement
  • order
  • preference
{
  flags: 's',
  service: 'SIP+D2U',
  regexp: '',
  replacement: '_sip._udp.example.com',
  order: 30,
  preference: 100
} 

dnsPromises.resolveNs(hostname)#

使用 DNS 協議解析 hostname 的名稱伺服器記錄(NS 記錄)。成功時,Promise 解析為一個可用於 hostname 的名稱伺服器記錄陣列(例如 ['ns1.example.com', 'ns2.example.com'])。

dnsPromises.resolvePtr(hostname)#

使用 DNS 協議解析 hostname 的指標記錄(PTR 記錄)。成功時,Promise 解析為一個包含應答記錄的字串陣列。

dnsPromises.resolveSoa(hostname)#

使用 DNS 協議解析 hostname 的起始授權機構記錄(SOA 記錄)。成功時,Promise 解析為一個具有以下屬性的物件:

  • nsname
  • hostmaster
  • serial
  • refresh
  • retry
  • expire
  • minttl
{
  nsname: 'ns.example.com',
  hostmaster: 'root.example.com',
  serial: 2013101809,
  refresh: 10000,
  retry: 2400,
  expire: 604800,
  minttl: 3600
} 

dnsPromises.resolveSrv(hostname)#

使用 DNS 協議解析 hostname 的服務記錄(SRV 記錄)。成功時,Promise 解析為一個具有以下屬性的物件陣列:

  • priority
  • weight
  • port
  • name
{
  priority: 10,
  weight: 5,
  port: 21223,
  name: 'service.example.com'
} 

dnsPromises.resolveTlsa(hostname)#

使用 DNS 協議解析 hostname 的證書關聯記錄(TLSA 記錄)。成功時,Promise 解析為一個具有以下屬性的物件陣列:

  • certUsage
  • selector
  • match
  • data
{
  certUsage: 3,
  selector: 1,
  match: 1,
  data: [ArrayBuffer]
} 

dnsPromises.resolveTxt(hostname)#

使用 DNS 協議解析 hostname 的文字查詢(TXT 記錄)。成功時,Promise 解析為一個二維陣列,其中包含 hostname 可用的文字記錄(例如 [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。每個子陣列包含一條記錄的 TXT 塊。根據用例,這些塊可以連線在一起或分開處理。

dnsPromises.reverse(ip)#

執行反向 DNS 查詢,將 IPv4 或 IPv6 地址解析為主機名陣列。

出錯時,Promise 會被一個 Error 物件拒絕,其中 err.codeDNS 錯誤程式碼之一。

dnsPromises.setDefaultResultOrder(order)#

  • order <string> 必須是 'ipv4first''ipv6first''verbatim'

設定 dns.lookup()dnsPromises.lookup()order 的預設值。該值可以是:

  • ipv4first:將預設 order 設定為 ipv4first
  • ipv6first:將預設 order 設定為 ipv6first
  • verbatim:將預設 order 設定為 verbatim

預設值為 verbatimdnsPromises.setDefaultResultOrder() 的優先順序高於 --dns-result-order。在使用 工作執行緒時,主執行緒的 dnsPromises.setDefaultResultOrder() 不會影響工作執行緒中的預設 dns 順序。

dnsPromises.getDefaultResultOrder()#

獲取 dnsOrder 的值。

dnsPromises.setServers(servers)#

設定執行 DNS 解析時要使用的伺服器的 IP 地址和埠。servers 引數是一個 RFC 5952 格式化地址的陣列。如果埠是 IANA 預設的 DNS 埠 (53),則可以省略。

dnsPromises.setServers([
  '8.8.8.8',
  '[2001:4860:4860::8888]',
  '8.8.8.8:1053',
  '[2001:4860:4860::8888]:1053',
]); 

如果提供了無效地址,將丟擲錯誤。

在 DNS 查詢進行中時,不得呼叫 dnsPromises.setServers() 方法。

此方法的工作方式很像 resolve.conf。也就是說,如果嘗試使用提供的第一個伺服器解析導致 NOTFOUND 錯誤,resolve() 方法將不會嘗試使用後續提供的伺服器進行解析。只有當較早的伺服器超時或導致其他錯誤時,才會使用備用 DNS 伺服器。

錯誤程式碼#

每個 DNS 查詢可能返回以下錯誤程式碼之一:

  • dns.NODATA:DNS 伺服器返回了無資料的應答。
  • dns.FORMERR:DNS 伺服器聲稱查詢格式錯誤。
  • dns.SERVFAIL:DNS 伺服器返回了一般性故障。
  • dns.NOTFOUND:未找到域名。
  • dns.NOTIMP:DNS 伺服器未實現請求的操作。
  • dns.REFUSED:DNS 伺服器拒絕了查詢。
  • dns.BADQUERY:DNS 查詢格式錯誤。
  • dns.BADNAME:主機名格式錯誤。
  • dns.BADFAMILY:不支援的地址族。
  • dns.BADRESP:DNS 回覆格式錯誤。
  • dns.CONNREFUSED:無法聯絡 DNS 伺服器。
  • dns.TIMEOUT:聯絡 DNS 伺服器時超時。
  • dns.EOF:檔案結尾。
  • dns.FILE:讀取檔案時出錯。
  • dns.NOMEM:記憶體不足。
  • dns.DESTRUCTION:通道正在被銷燬。
  • dns.BADSTR:字串格式錯誤。
  • dns.BADFLAGS:指定了非法的標誌。
  • dns.NONAME:給定的主機名不是數字。
  • dns.BADHINTS:指定了非法的提示標誌。
  • dns.NOTINITIALIZED:c-ares 庫尚未初始化。
  • dns.LOADIPHLPAPI:載入 iphlpapi.dll 時出錯。
  • dns.ADDRGETNETWORKPARAMS:無法找到 GetNetworkParams 函式。
  • dns.CANCELLED:DNS 查詢已取消。

dnsPromises API 也匯出了上述錯誤程式碼,例如 dnsPromises.NODATA

實現注意事項#

雖然 dns.lookup() 和各種 dns.resolve*()/dns.reverse() 函式的目標相同,都是將網路名稱與網路地址(或反之)關聯起來,但它們的行為卻大相徑庭。這些差異可能對 Node.js 程式的行為產生細微但重大的影響。

dns.lookup()#

在底層,dns.lookup() 使用與大多數其他程式相同的作業系統設施。例如,dns.lookup() 幾乎總是以與 ping 命令相同的方式解析給定的名稱。在大多數類 POSIX 作業系統上,可以透過更改 nsswitch.conf(5) 和/或 resolv.conf(5) 中的設定來修改 dns.lookup() 函式的行為,但更改這些檔案將改變同一作業系統上執行的所有其他程式的行為。

儘管從 JavaScript 的角度來看,對 dns.lookup() 的呼叫是非同步的,但它被實現為對在 libuv 執行緒池上執行的 getaddrinfo(3) 的同步呼叫。這可能對某些應用程式產生意想不到的負面性能影響,有關更多資訊,請參閱 UV_THREADPOOL_SIZE 文件。

各種網路 API 會在內部呼叫 dns.lookup() 來解析主機名。如果這是一個問題,可以考慮使用 dns.resolve() 將主機名解析為地址,並使用地址代替主機名。此外,一些網路 API(例如 socket.connect()dgram.createSocket())允許替換預設解析器 dns.lookup()

dns.resolve()dns.resolve*()dns.reverse()#

這些函式的實現與 dns.lookup() 大不相同。它們不使用 getaddrinfo(3),並且它們總是在網路上執行 DNS 查詢。這種網路通訊總是非同步完成的,並且不使用 libuv 的執行緒池。

因此,這些函式不會像 dns.lookup() 那樣對 libuv 執行緒池上發生的其他處理產生相同的負面影響。

它們不使用與 dns.lookup() 相同的配置檔案集。例如,它們不使用 /etc/hosts 中的配置。