الوحدة ‎‎‎DNS‎ في Node.js

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

الاستقرار: 2-مستقر

تحتوي الوحدة dns على دوال تخص فئتين مختلفتين هما:

  • الدوال التي تستعمل خدمات نظام التشغيل الضمنية لتنفيذ عملية استبيان الاسم (name resolution)، والتي لا تتطلب بالضرورة تنفيذ أية عمليات اتصال بالشبكة. تحوي هذه الفئة على دالة وحيدة هي dns.lookup()‎. يتطلع المطورون إلى تنفيذ عملية استبيان الاسم بالطريقة نفسها التي تُنفِّذ فيها التطبيقات الأخرى الدالة dns.lookup() على المنصة ذاتها عندما تضطر إلى استعمالها. تفحَّص المثال التالي الذي يُستعمَل فيه الدالة dns.lookup() للبحث عن iana.org‎:
const dns = require('dns');

dns.lookup('iana.org', (err, address, family) => {
  console.log('address: %j family: IPv%s', address, family);
});
// address: "192.0.43.8" family: IPv4
  • الدوال التي تتصل بخادم DNS حقيقي لتنفيذ عملية استبيان الاسم، والتي تستعمل دومًا الشكبة لتنفيذ استعلامات DNS. تتألف هذه الفئة من جميع الدوال الموجودة في الوحدة dns باستثناء الدالة dns.lookup(). لا تستعمل هذه الدوال مجموعة ملفات الضبط نفسها التي تستعملها الدالة dns.lookup() (مثل ‎/etc/hosts). يجب أن يستعمل هذه الدوال المطورون الذين لا يريدون أن يستخدموا خدمات نظام التشغيل الضمنية لاستبيان الاسم ولكن يريدون بدلًا من ذلك تنفيذ استعلامات DNS.
const dns = require('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‎

أضيف في الإصدار: v8.3.0.

يعدُّ الصنف dns.Resolver‎‎ مستبيِن مستقل (independent resolver) من أجل طلبات DNS.

انتبه إلى أنَّ المستبين المُنشَأ حديثًا يستعمل إعدادات الخادم الافتراضية. ضبط الخوادم المستعملة من أجل مستبين معيَّن عبر resolver.setServers()‎ ليس له تأثير على مستبينات أخرى:

const { Resolver } = require('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) => {
  // ...
});

التوابع التالية من الوحدة dns متاحةٌ حاليًا:

resolver.cancel()‎

أضيف في الإصدار: v8.3.0.

يلغي هذا التابع جميع استعلامات DNS المعلقة التي أنشأها هذا المستبين. ستُستدعَى دوال ردود النداء المقابلة مع خطأٍ رمزه ECANCELLED.

dns.getServers()‎

أضيف في الإصدار: v0.11.3.

يعيد هذا التابع مصفوفةً من سلاسل نصية تمثِّل عناوين IP، منسقةً وفقًا للمعيار rtc5952، التي ضُبطَت آنذاك لتحليل DNS. ستتضمن السلسلة النصية جزءًا للمنفذ إن استخدم منفذ مخصص.

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

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

سجل التغييرات
الإصدار التغييرات
v1.2.0 أصبح الخيار all مدعومًا الآن.
v0.1.90 أضيف هذا التابع.
  • hostname‎:‏ <string>
  • options‎: ‏<integer>‏ | <Object>
    • family‎: ‏<integer> عائلة السجل. يجب أن يأخذ القيمة 4 أو 6. يعاد العنوان IPv4 والعنوان IPv6 كلاهما افتراضيًّا.
    • hints‎: ‏<number> واحدةٌ أو أكثر من الرايات getaddrinfo‎ المدعومة. يمكن تمرير رايات متعددة عبر دمجها باستعمال المعامل OR الثنائي.
    • all‎: ‏‏<boolean> عندما تكون قيمته true، يعيد رد النداء جميع العناوين المستبينة في مصفوفة. خلا ذلك، يعيد عنوانًا واحدًا فقط. القيمة الافتراضية هي: false.
    • verbatim‎: ‏<boolean> عندما تكون قيمته true، يستقبل رد النداء العناوين IPv4 و IPv6 بالترتيب الذي أعاده بهم المستبين DNS. عندما تكون قيمته false، توضع العناوين IPv4 قبل عناوين IPv6. القيمة الافتراضية حاليًا هي: false (أي يعاد ترتيب العناوين)، ولكن يُتوقع أن تتغير في المستقبل القريب. يجب أن تستعمل الشيفرات الجديدة القيمة { verbatim: true }‎.
  • callback‎: ‏<Function>
    • err‎: ‏<Error>
    • address‎: ‏<string> سلسلة نصية تمثل عناوين IPv4 أو IPv6.
    • family: ‏<integer> عدد صحيح قيمته إما 4 أو 6 يدُّل على عائلة العنوان address.

يستبين هذا التابع اسم المضيف (hostname) -مثل 'nodejs.org'‎- إلى أول سجل A (أي IPv4) أو AAAA (أي IPv6) يعثر عليه. إن كان الوسيط options عددًا صحيحًا، فيجب أن تكون قيمته 4 أو 6. أمَّا إن لم يُعطَ الوسيط options، فستُعاد العناوين IPv4 و IPv6 كلاهما حينئذٍ إن عُثِر عليها.

عند ضبط الخيار all إلى القيمة true، فستتغيَّر وسائط رد النداء callback إلى (err, addresses)‎ مع جعل الوسيط addresses مصفوفةً من كائنات لها الخاصيتين address و family.

في حال حصول خطأ، يكون الوسيط err‎ كائنًا من النوع Error‎، إذ يكون err.code‎ هو رمز الخطأ. تذكر دومًا أنَّ err.code‎ سيضبط إلى القيمة 'ENOENT'‎ ليس عندما لا يوجد اسم مضيف فقط ولكن عند فشل عملية البحث (lookup) أيضًا بطرق أخرى مثل عدم توافر واصفات للملف (file descriptors).

ليس بالضرورة أن تملك الدالة dns.lookup()‎ كل شيء مطلوب للعمل مع البروتوكول DNS، إذ يستعمل التنفيذ خدمات نظام التشغيل التي تستطيع ربط الأسماء بالعناوين والعكس بالعكس. لهذا التنفيذ عواقب غامضة ولكن مهمة تؤثِّر على سلوك أي تطبيق من تطبيقات Node.js. خذ بعض الوقت رجاءً لقراءة وتفحِّص القسم «اعتبارات التنفيذ» -في الأسفل- قبل استعمال التابع dns.lookup()‎.

const dns = require('dns');
const options = {
  family: 6,
  hints: dns.ADDRCONFIG | dns.V4MAPPED,
};
dns.lookup('example.com', options, (err, address, family) =>
  console.log('address: %j family: IPv%s', address, 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;
dns.lookup('example.com', options, (err, addresses) =>
  console.log('addresses: %j', addresses));
// addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}]

إن استدعي هذا التابع مثل نظيره util.promisify()‎ ولم يُضبَط الوسيط all إلى القيمة true، فسيُعيد كائنًا من النوع Promise لكائن Object‎ مع الخاصيتين address‎ و family.

الرايات getaddrinfo‎ المدعومة

يمكن استعمال الرايات التالية مع الوسيط hints‎ الممرر إلى التابع dns.lookup()‎:

  • dns.ADDRCONFIG‎: تحدِّد أنواع العناوين المعادة عبر أنواع العناوين المدعومة من قِبَل النظام الحالي. على سبيل المثال، تعاد العناوين IPv4 فقط إن كان النظام الحالي يملك عنوان IPv4 واحد مضبوط على الأقل. لا تؤخذ العناوين loopback بالحسبان.
  • dns.V4MAPPED‎: إن حُدِّدت عائلة العناوين IPv6 ولكن لم يُعثَر على عناوين IPv6، فستُعاد حينئذٍ العناوين IPv4 بعد تعيينها إلى عناوين IPv6. انتبه إلى أنَّ هذه الراية غير مدعومة على بعض أنظمة التشغيل (مثل FreeBSD 10.1).

dns.lookupService(address, port, callback)‎

أضيف في الإصدار: 0.11.14.

يستبين هذا التابع العنوان address والمنفذ port‎ المعطى إلى اسم مضيف (hostname) وخدمة (service) باستعمال التنفيذ getnameinfo‎ الضمني لنظام التشغيل. إن لم يكن الوسيط address‎ عنوان IP صالح، فسيُرمَى الخطأ TypeError‎. سيحوَّل المنفذ port‎ إلى عدد رغمًا عنه؛ فإن لم يكن منفذًا مقبولًا، فسيُرمى الخطأ TypeError‎. في حال حصول خطأ، يكون الوسيط err‎ كائنًا من النوع Error‎، إذ يكون err.code‎ هو رمز الخطأ.

const dns = require('dns');
dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
  console.log(hostname, service);
  // localhost ssh :سيُطبع
});

إن استدعي هذا التابع مثل نظيره util.promisify()‎، فسيعيد كائنًا من النوع Promise للكائن Object‎ مع الخاصيتين address‎ و family.

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

أضيف في الإصدار: v0.1.27.

يستعمل هذا التابع بروتوكول DNS للاستبيان عن اسم مضيف (مثل 'nodejs.org'‎) إلى مصفوفة من سجلات المصدر (resource records). يُمرَّر إلى الدالة callback‎ الوسيطين err‎ و records‎. عند نجاح العملية، سيكون records‎ مصفوفةً من سجلات المصدر. يختلف نوع وبنية النتائج الفردية التي نحصل عليها بناءً على قيمة الوسيط rrtype‎ وهي:

rrtype محتويات السجلات records نوع النتيجة التابع المختصر المقابل
'A' عناوين IPv4 (القيمة الافتراضية). <string> dns.resolve4()‎
'AAAA' عناوين IPv6. <string> dns.resolve6()‎
'ANY' أية سجلات. <Object> resolver.resolveAny()‎
'CNAME' سجلات الاسم المعياري (canonical name records). <string> dns.resolveCname()‎
'MX' سجلات تبادل البريد (mail exchange records). <Object> resolver.resolveMx()‎
'NAPTR' سجلات مؤشر اسم التفويض (name authority pointer records). <Object> dns.resolveNaptr()‎
'NS' سجلات خادم الأسماء (Name Server). <string> dns.resolveNs()‎
'PTR' سجلات المؤشر (pointer records). <string> dns.resolvePtr()‎
'SOA' بداية سجلات التفويض  (authority records). <Object> dns.resolveSoa()‎
'SRV' سجلات خدمة (service records). <Object> dns.resolveSrv()‎
'TXT' سجلات نصية (text records). <string[]‎> dns.resolveTxt()‎

في حال حصول خطأ، يكون الوسيط err‎ كائنًا من النوع Error‎، إذ يعدُّ err.code‎ أحد رموز الخطأ في DNS.

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

سجل التغييرات
الإصدار التغييرات
v7.2.0 أصبح هذا التابع يدعم تمرير الوسيط options‎ خصوصًا options.ttl‎.
v0.1.16 أضيف هذا التابع.
  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.
  • options:‏ <Object>
    • ttl:‏ <boolean> استرجاع قيمة «العمر» (TTL، اختصارٌ للعبارة Time-To-Live). عندما تكون قيمته true، تستقبل دالة رد النداء مصفوفة من الكائنات { address: '1.2.3.4', ttl: 60 }‎ بدلًا من مصفوفة من السلاسل النصية، ومع التعبير عن «العمر» بالثواني.
  • callback:‏ <Function>

يستعمل هذا التابع بروتوكول DNS لاستبيان عناوين IPv4 (سجلات 'A') من أجل اسم المضيف hostname‎. سيحوي الوسيط addresses‎ المُمرَّر إلى الدالة callback‎ مصفوفةً من عناوين IPv4 (مثل ['74.125.79.104', '74.125.79.105', '74.125.79.106']‎).

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

سجل التغييرات
الإصدار التغييرات
v7.2.0 أصبح هذا التابع يدعم تمرير الوسيط options‎ خصوصًا options.ttl‎.
v0.1.16 أضيف هذا التابع.
  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.
  • options:‏ <Object>
    • ttl:‏ <boolean> استرجاع قيمة «العمر» (TTL، اختصارٌ للعبارة Time-To-Live). عندما تكون قيمته true، تستقبل دالة رد النداء مصفوفة من الكائنات { address: '1.2.3.4', ttl: 60 }‎ بدلًا من مصفوفة من السلاسل النصية، ومع التعبير عن «العمر» بالثواني.
  • callback:‏ <Function>

يستعمل هذا التابع بروتوكول DNS لاستبيان عناوين IPv6 (سجلات 'AAAA') من أجل اسم المضيف hostname‎. سيحوي الوسيط addresses‎ المُمرَّر إلى الدالة callback‎ مصفوفةً من عناوين IPv6.

dns.resolveAny(hostname, callback)‎

يستعمل هذا التابع بروتوكول DNS لاستبيان جميع السجلات (يُعرَف أيضًا بأنه استعلام ANY‎ أو *‎). سيحوي الوسيط ret المُمرَّر إلى الدالة callback‎ مصفوفةً تحتوي على مختلف أنواع السجلات. يملك كل سجل الخاصية 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()‎.
'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.resolveCname(hostname, callback)‎

أضيف في الإصدار: v0.3.2.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات البريد المتبادل (سجلات MX‎) لاسم المضيف hostname‎. سيحوي الوسيط addresses المُمرَّر إلى الدالة callback‎ مصفوفةً من الكائنات التي تحتوي على الخاصية priority‎ والخاصية exchange‎ (مثل [{priority: 10, exchange: 'mx.example.com'}, ...]‎).

dns.resolveMx(hostname)‎

أضيف في الإصدار: v10.6.0.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات البريد المتبادل (سجلات MX‎) لاسم المضيف hostname‎. سيحوي الوسيط addresses المُمرَّر إلى الدالة callback‎ مصفوفةً من الكائنات التي تحتوي على الخاصية priority‎ والخاصية exchange‎ (مثل [{priority: 10, exchange: 'mx.example.com'}, ...]‎).

dns.resolveNaptr(hostname, callback)‎

أضيف في الإصدار: v0.9.12.

يستعمل هذا التابع بروتوكول DNS لاستبيان السجلات القائمة على تعابير نمطية (سجلات NAPTR) لاسم المضيف hostname‎. سيحوي الوسيط addresses المُمرَّر إلى الدالة callback‎ مصفوفةً من كائناتٍ لها الخاصيات التالية:

  • 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)‎

أضيف في الإصدار: v0.1.90.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات اسم الخادم (سجلات NS‎) لاسم المضيف hostname‎. سيحوي الوسيط addresses المُمرَّر إلى الدالة callback‎ مصفوفةً من سجلات اسم الخادم المتوافرة لاسم للمضيف hostname‎ (مثل ['ns1.example.com', 'ns2.example.com']‎).

dns.resolvePtr(hostname, callback)‎

أضيف في الإصدار: v6.0.0.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات المؤشر (سجلات PTR) لاسم المضيف hostname‎. سيحوي الوسيط addresses المُمرَّر إلى الدالة callback‎ مصفوفةً من السلاسل النصية التي تحتوي على سجلات الرد (reply records).

dns.resolveSoa(hostname, callback)‎

أضيف في الإصدار: v0.11.10.

يستعمل هذا التابع بروتوكول DNS لاستبيان بداية سجل التفويض (سجل SOA) لاسم المضيف hostname‎. الوسيط addresses المُمرَّر إلى الدالة callback‎ هو كائنٌ يملك الخاصيات التالية:

  • 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)‎

أضيف في الإصدار: v0.1.27.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات خدمة (سجلات SRV) لاسم المضيف hostname‎. الوسيط addresses المُمرَّر إلى الدالة callback‎ هو مصفوفة من كائنات تمتلك الخاصيات التالية:

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

dns.resolveTxt(hostname, callback)‎

أضيف في الإصدار: v0.1.27.

يستعمل هذا التابع بروتوكول DNS لاستبيان استعلامات نصية (سجلات TXT) لاسم المضيف hostname‎. الوسيط addresses المُمرَّر إلى الدالة callback‎ هو مصفوفة ثنائية البعد من سجلات نصية لاسم المضيف hostname‎ (مثل [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]‎). تحتوي كل مصفوفة فرعية على قطع TXT لسجل واحد. بناءً على حالة الاستعمال، يمكن أن يُجمَّعوا سويةً أو يعاملوا بشكل منفصل.

dns.reverse(ip, callback)‎

أضيف في الإصدار: 0.1.16.

ينفِّذ هذا التابع تعليمة DNS بشكل عكسي لاستبيان عناوين IPv4 أو IPv6 إلى مصفوفة من أسماء المضيفين.

عند حصول خطأ، يكون الوسيط err‎ كائنًا من النوع Error‎، إذ يعدُّ err.code‎ واحدًا من رموز الخطأ في DNS.

dns.setServers(servers)‎

أضيف في الإصدار: v0.11.3.

  • servers‎:‏ <string[]‎> مصفوفة من سلاسل نصية تمثِّل عناوين منسقة وفقًا للتنسيق المحدد في المعيار rfc5952.

يضبط هذا التابع العناوين IP ومنافذ الخوادم لاستعمالها عند تنفيذ استبيان DNS. الوسيط servers‎ هو مصفوفة من سلاسل نصية تمثِّل عناوينًا منسقةً وفقًا للتنسيق المحدد في المعيار rfc5952. إن كان المنفذ هو منفذ DNS الافتراضي الذي حددته IANA (وهو 53)، فيمكن حذفه.

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

سيُرمَى خطأ إن أعطي عنوان غير صالح.

يجب ألا يُستدعَى التابع dns.setServers()‎ عندما تكون إحدى تعليمات DNS قيد المعالجة.

انتبه إلى أنَّ هذا التابع يعمل بشكل مشابه تقريبًا للدالة resolve.conf‎. هذا يعني أنَّه إن أعطت محاولة إجراء استبيان من أول خادم خطأً من النوع NOTFOUND‎، فلن يحاول التابع resolve()‎ إكمال عملية الاستبيان من الخوادم اللاحقة المعطاة. سيُلجَأ إلى استعادة خوادم DNS والرجوع إليها إن انتهت مهلة سابقاتها أو احتوى الناتج على أخطاء أخرى فقط.

واجهة وعود DNS البرمجية (DNS Promises API)

الاستقرار: 1-قيد التجريب.

توفِّر الواجهة dns.promises‎ البرمجية مجموعةً بديلةً لتوابع DNS غير المتزامنة التي تعيد كائنات من النوع Promise‎ بدلًا من استعمال ردود النداء. يمكن الوصول إلى الواجهة البرمجية عبر require('dns').promises‎.

الصنف dnsPromises.Resolver‎

أضيف في الإصدار: v10.6.0.

يعدُّ الصنف dnsPromises.Resolver‎‎ مستبينًا مستقلًا لطلبات DNS.

انتبه إلى أنَّه ستُستعمَل إعدادات الخادم الافتراضية عند إنشاء مستبين جديد. لا تؤثر عملية ضبط الخوادم التي يستعملها مستبين معيَّن عبر التابع resolver.setServers()‎ على بقية المستبينات:

 
const { Resolver } = require('dns').promises;
const resolver = new Resolver();
resolver.setServers(['4.4.4.4']);

// سيستعمل هذا الطلب الخادم عند 4.4.4.4 بشكل مستقل عن الإعدادات العامة
resolver.resolve4('example.org').then((addresses) => {
  // ...
});

// async-await بدلًا من ذلك، يمكن كتابة نفس الشيفرة باستعمال النمط 
(async function() {
  const addresses = await resolver.resolve4('example.org');
})();

توابع الواجهة dnsPromises‎ البرمجية المتاحة الآن هي:

dnsPromises.getServers()‎

أضيف في الإصدار: v0.11.3.

يعيد هذا التابع مصفوفةً من سلاسل نصية تمثِّل عناوين IP، منسقةً وفقًا للمعيار rtc5952، التي ضُبطَت آنذاك لتحليل DNS. ستتضمن السلسلة النصية جزءًا للمنفذ إن استخدم منفذ مخصص.

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

dnsPromises.lookup(hostname[, options])‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string>
  • options‎: ‏<integer>‏ | <Object>
    • family‎: ‏<integer> عائلة السجل. يجب أن يأخذ القيمة 4 أو 6. يعاد العنوان IPv4 والعنوان IPv6 كلاهما افتراضيًّا.
    • hints‎: ‏<number> واحدةٌ أو أكثر من الرايات getaddrinfo‎ المدعومة. يمكن تمرير رايات متعددة عبر دمجها باستعمال المعامل OR الثنائي.
    • all‎: ‏‏<boolean> عندما تكون قيمته true، يُستبيَن الكائن Promise‎ مع جميع العناوين الموجودة في مصفوفة. خلا ذلك، يعيد عنوانًا واحدًا فقط. القيمة الافتراضية هي: false.
    • verbatim‎: ‏<boolean> عندما تكون قيمته true، يُستبيَن الكائن Promise‎ مع العناوين IPv4 و IPv6 بالترتيب الذي أعاده بهم مستبين DNS. عندما تكون قيمته false، توضع العناوين IPv4 قبل عناوين IPv6. القيمة الافتراضية حاليًا هي: false (أي يعاد ترتيب العناوين)، ولكن يُتوقع أن تتغير في المستقبل القريب. يجب أن تستعمل الشيفرات الجديدة القيمة { verbatim: true }‎.

يستبين هذا التابع اسم المضيف (hostname) -مثل 'nodejs.org'‎- إلى أول سجل A (أي IPv4) أو AAAA (أي IPv6) يعثر عليه. جميع خيارات الكائن option‎ هي اختيارية. إن كان الوسيط options عددًا صحيحًا، فيجب أن تكون قيمته 4 أو 6. أما إن لم يُعطَ الوسيط options، فستُعاد العناوين IPv4 و IPv6 كلاهما حينئذٍ إن عُثِر عليها. عند ضبط الخيار all إلى القيمة true، يُستبيَن الكائن Promise مع جعل الوسيط addresses‎ مصفوفةً من كائنات لها الخاصيتين address‎ و family‎.

في حال حصول خطأ، يُرفَض الكائن Promise مع كائن من النوع Error‎ إذ يكون err.code‎ رمز الخطأ. تذكر دومًا أنَّ err.code‎ سيُضبَط إلى القيمة 'ENOENT'‎ ليس عندما لا يوجد اسم مضيف فقط ولكن عند فشل عملية البحث (lookup) أيضًا بطرائق أخرى مثل عدم توافر واصفات للملف (file descriptors).

ليس بالضرورة أن تملك الدالة dns.lookup()‎ كل شيء مطلوب للعمل مع البروتوكول DNS، إذ يستعمل التنفيذ خدمات نظام التشغيل التي تستطيع ربط الأسماء بالعناوين والعكس بالعكس. لهذا التنفيذ عواقب غامضة ولكن مهمة تؤثر على سلوك أي تطبيق من تطبيقات Node.js. خذ بعض الوقت رجاءً لقراءة وتفحِّص القسم «اعتبارات التنفيذ» -في الأسفل- قبل استعمال التابع dns.lookup()‎.

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)‎

أضيف في الإصدار: v10.6.0.

يستبين هذا التابع العنوان address والمنفذ port‎ المعطى إلى اسم مضيف (hostname) وخدمة (service) باستعمال التنفيذ getnameinfo‎ الضمني لنظام التشغيل.

إن لم يكن الوسيط address‎ عنوان IP صالح، فسيُرمى الخطأ TypeError‎. سيحوَّل المنفذ port‎ إلى عدد رغمًا عنه؛ فإن لم يكن منفذًا شرعيًّا، فسيُرمى الخطأ TypeError‎.

في حال حصول خطأ، يُرفَض الكائن Promise مع كائن من النوع Error‎، إذ يكون err.code‎ هو رمز الخطأ.

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])‎

أضيف في الإصدار: v0.1.27.

  • hostname‎:‏ <string> اسم الضيف الذي سيُستبيَن.
  • rrtype‎:‏ <string> نوع سجل المصدر. القيمة الافتراضية هي: 'A'.

يستعمل هذا التابع بروتوكول DNS للاستبيان عن اسم مضيف (مثل 'nodejs.org'‎) إلى مصفوفة من سجلات المصدر (resource records). يُقبَل الكائن Promise‎ مع مصفوفة من سجلات المصدر عند نجاح العملية. يختلف نوع وبنية النتائج الفردية التي نحصل عليها بناءً على قيمة الوسيط rrtype‎ وهي:

rrtype محتويات السجلات records نوع النتيجة التابع المختصر المقابل
'A' عناوين IPv4 (القيمة الافتراضية). <string> dnsPromises.resolve4()‎
'AAAA' عناوين IPv6. <string> dnsPromises.resolve6()‎
'ANY' أية سجلات. <Object> dnsPromises.resolveAny()‎
'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). <string> dnsPromises.resolveNs()‎
'PTR' سجلات المؤشر (pointer records). <string> dnsPromises.resolvePtr()‎
'SOA' بداية سجلات التفويض  (authority records). <Object> dnsPromises.resolveSoa()
'SRV' سجلات خدمة (service records). <Object> dnsPromises.resolveSrv()‎
'TXT' سجلات نصية (text records). <string[]‎> dnsPromises.resolveTxt()‎

في حال حصول خطأ، يُرفَض الكائن Promise مع كائن من النوع Error‎، إذ يعدُّ err.code‎ أحد رموز الخطأ في DNS.

dnsPromises.resolve4(hostname[, options])‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.
  • options:‏ <Object>
    • ttl:‏ <boolean> استرجاع قيمة «العمر» (TTL، اختصارٌ للعبارة Time-To-Live). عندما تكون قيمته true، يُقبَل الكائن Promise‎ مع مصفوفة من الكائنات { address: '1.2.3.4', ttl: 60 }‎ بدلًا من مصفوفة من السلاسل النصية، ومع التعبير عن «العمر» بالثواني.

يستعمل هذا التابع بروتوكول DNS لاستبيان عناوين IPv4 (سجلات 'A') من أجل اسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفةً من عناوين IPv4 (مثل ['74.125.79.104', '74.125.79.105', '74.125.79.106']‎).

dnsPromises.resolve6(hostname[, options])‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.
  • options:‏ <Object>
    • ttl:‏ <boolean> استرجاع قيمة «العمر» (TTL، اختصارٌ للعبارة Time-To-Live). عندما تكون قيمته true، يُقبَل الكائن Promise‎ مع مصفوفة من الكائنات { address: '1.2.3.4', ttl: 60 }‎ بدلًا من مصفوفة من السلاسل النصية، ومع التعبير عن «العمر» بالثواني.

يستعمل هذا التابع بروتوكول DNS لاستبيان عناوين IPv6 (سجلات 'AAAA') من أجل اسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفةً من عناوين IPv6.

dnsPromises.resolveAny(hostname)‎

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.

يستعمل هذا التابع بروتوكول 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()‎‎.
'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.resolveCname(hostname)‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات CNAME لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفةً من سجلات الاسم المعياري المتاحة لاسم المضيف hostname‎ (مثل ['bar.example.com']‎).

dnsPromises.resolveMx(hostname)‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات البريد المتبادل (سجلات MX‎) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفةً من الكائنات التي تحتوي على الخاصية priority‎ والخاصية exchange‎ (مثل [{priority: 10, exchange: 'mx.example.com'}, ...]‎).

dnsPromises.resolveNaptr(hostname)‎

أضيف في الإصدار: v10.6.0.

  • hostname‎:‏ <string> اسم المضيف المراد استبيناه.

يستعمل هذا التابع بروتوكول DNS لاستبيان السجلات القائمة على تعابير نمطية (سجلات NAPTR) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن 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)‎

أضيف في الإصدار: v10.6.0.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات اسم الخادم (سجلات NS‎) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفةً من سجلات اسم الخادم المتوافرة لاسم للمضيف hostname‎ (مثل ['ns1.example.com', 'ns2.example.com']‎).

dnsPromises.resolvePtr(hostname)‎

أضيف في الإصدار: v10.6.0.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات المؤشر (سجلات PTR) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفة من السلاسل النصية التي تحتوي على سجلات الرد (reply records).

dnsPromises.resolveSoa(hostname)‎

أضيف في الإصدار: v10.6.0.

يستعمل هذا التابع بروتوكول DNS لاستبيان بداية سجل التفويض (سجل SOA) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن 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)‎

أضيف في الإصدار: v0.1.27.

يستعمل هذا التابع بروتوكول DNS لاستبيان سجلات خدمة (سجلات SRV) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفة من كائنات تمتلك الخاصيات التالية:

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

dnsPromises.resolveTxt(hostname)‎

أضيف في الإصدار: v0.1.27.

يستعمل هذا التابع بروتوكول DNS لاستبيان استعلامات نصية (سجلات TXT) لاسم المضيف hostname‎. عند نجاح العملية، يُقبَل الكائن Promise‎ مع مصفوفة ثنائية البعد من السجلات النصية المتوافرة لاسم المضيف hostname‎ (مثل [ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]‎). تحتوي كل مصفوفة فرعية على قطع TXT لسجل واحد. بناءً على حالة الاستعمال، يمكن أن يُجمَّعوا سويةً أو يعاملوا بشكل منفصل.

dnsPromises.reverse(ip)‎

أضيف في الإصدار: v10.6.0.

ينفِّذ هذا التابع تعليمة DNS بشكل عكسي لاستبيان عناوين IPv4 أو IPv6 إلى مصفوفة من أسماء المضيفين. عند حصول خطأ، يُرفَض الكائن Promise مع كائن من النوع Error‎، إذ يعدُّ err.code‎ واحدًا من رموز الخطأ في DNS.

dnsPromises.setServers(servers)‎

أضيف في الإصدار: v10.6.0.

  • servers‎:‏ <string[]‎> مصفوفة من سلاسل نصية تمثِّل عناوين منسقة وفقًا للتنسيق المحدد في المعيار rfc5952.

يضبط هذا التابع العناوين IP ومنافذ الخوادم لاستعمالها عند تنفيذ استبيان DNS. الوسيط servers‎ هو مصفوفة من سلاسل نصية تمثِّل عناوين منسقة وفقًا للتنسيق المحدد في المعيار rfc5952. إن كان المنفذ هو منفذ DNS الافتراضي الذي حددته IANA (وهو 53)، فيمكن حذفه حينئذٍ.

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

سيُرمَى خطأ إن أعطي عنوان غير صالح.

يجب ألا يُستدعَى التابع dnsPromises.setServers()‎ عندما تكون إحدى تعليمات DNS قيد المعالجة.

انتبه إلى أنَّ هذا التابع يعمل بشكل مشابه تقريبًا للدالة resolve.conf‎. هذا يعني أنَّه إن أعطت محاولة إجراء استبيان من أول خادم خطأً من النوع NOTFOUND‎، فلن يحاول التابع resolve()‎ إكمال عملية الاستبيان من الخوادم اللاحقة المعطاة. سيُلجَأ إلى استعادة خوادم DNS والرجوع إليها إن انتهت مهلة سابقاتها أو احتوى الناتج على أخطاء أخرى فقط.

رموز الخطأ (Error codes)

يمكن لأي تعليمة من تعليمات DNS أن تعيد أحد رموز الخطأ التالية:

رمز الخطأ الوصف
dns.NODATA‎ أعاد خادم DNS ردًا دون احتوائه على أية بيانات
dns.FORMERR تعليمة مطالبات (claims) خادم DNS غير منسقة بشكل صحيح.
dns.SERVFAIL أعاد خادم DNS خطأ عام.
dns.NOTFOUND لم يُعثر على اسم النطاق (domain name).
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 الرايات hints‎ المحددة أو إحداها غير مقبولة.
dns.NOTINITIALIZED لم تنجز عملية تهيئة المكتبة c-ares بعد.
dns.LOADIPHLPAPI حصل خطأ أثناء تحميل الملف iphlpapi.dll.
dns.ADDRGETNETWORKPARAMS لم يُعثَر على الدالة GetNetworkParams.
dns.CANCELLED أُلغيَت تعليمة DNS.

اعتبارات التنفيذ

رغم أنَّ التابع dns.lookup()‎ والتوابع dns.resolve*()/dns.reverse()‎ الأخرى لديها الهدف نفسه وهو ربط اسم شبكة معين بعنوانها (أو العكس) إلا أنَّ سلوك كل منهما مختلف بعض الشيء. قد تؤدي هذه الاختلافات إلى عواقب غامضة ولكن مهمة تؤثر على سلوك تطبيق Node.js ككل.

dns.lookup()‎

إن تعمَّقنا بعض الشيء، نجد أنَّ التابع dns.lookup()‎ يستعمل نفس خدمات نظام التشغيل كما تفعل أغلب التطبيقات الأخرى. على سبيل المثال، يستبين التابع dns.lookup()‎ الاسم المعطى بالطريقة نفسها تقريبًا بشكل دائم مثلما يفعل الأمر ping‎. في أغلب الأنظمة المتوافقة مع المعيار POSIX، يمكن تعديل سلوك التابع dns.lookup()‎ عبر تغيير الإعدادات في nsswitch.conf(5) و/أو resolv.conf(5)‎، ولكن انتبه إلى أنَّ تغيير هذه الملفات سيُغيِّر سلوك جميع البرامج الأخرى التي تعمل على نظام التشغيل نفسه.

رغم أنَّ استدعاء التابع dns.lookup()‎ سيكون غير متزامن من وجهة نظر JavaScript إلا أنَّه يُنفَّذ كما لو كان استدعاءً متزامنًا للدالة getaddrinfo(3) التي تعمل على مجمع خيط (threadpool) المكتبة libuv. ويمكن أن يترتَّب على هذا الأمر آثارًا سلبيةً على الأداء لبعض التطبيقات. لمزيد من التفاصيل، اطلع على قسم الخيار UV_THREADPOOL_SIZE‎ في توثيق خيارات سطر الأوامر في Node.js.

انتبه إلى أنَّ مختلف واجهات الشبكة البرمجية (networking APIs) ستستدعي التابع dns.lookup()‎ بشكل داخلي لاستبيان أسماء المضيف. إن كان ذلك مشكلةً، فاعتمد على استبيان اسم المضيف إلى عنوان باستعمال التابع dns.resolve()‎ واستخدم العناوين بدلًا من اسم المضيف. أضف إلى ذلك، بعض واجهة الشبكة البرمجية (مثل socket.connect() و dgram.createSocket()‎) تسمح باستبدال المستبين الافتراضي، الذي هو dns.lookup()‎.

التابع dns.resolve()‎، والتوابع dns.resolve*()‎، والتابع dns.reverse()‎

تنفَّذ هذه التوابع بشكل مختلف إلى حد كبير عن التابع dns.lookup()‎. إنها لا تستعمل الدالة getaddrinfo(3)‎ وتنفِّذ أحد استعلامات DNS على الشبكة دومًا. تجري هذه الاتصالات على الشبكة بشكل غير متزامن دومًا، ولا ستعمل مجمع خيوط المكتبة libuv مطلقًا.

نتيجةً لذلك، لا يمكن أن يكون لهذه التوابع نفس التأثير السلبي على عمليات المعالجة الأخرى التي تقع في مجمع خيوط المكتبة libuv بخلاف التابع dns.lookup()‎.

أضف إلى ذلك أنَّ هذه التوابع لا تستعمل مجموعة ملفات الضبط نفسها كما يفعل التابع dns.lookup()‎. على سبيل المثال، نجد أنَّها لا تستعمل ملف الضبط الموجود في /etc/hosts‎.

مصادر