Search

What Is the Use of DNS Module in Node.Js?

Node.js gives the provision of using different modules. In this article, we will look into the use of DNS module in Node.  What is DNS and its importance?DNS stands for Domain Name System. The main function of the DNS is to translate the IP Address, which is a numerical label assigned to your computer. IP addresses can be thought of as names of computers on a network and are used to distinguish different devices and their locations.  For example, 8.8.8.8 is one of the many public IP addresses of Google.com. So, DNS can be considered as phonebook of the Internet. When we type any address like www.example.com in our browser, that request is sent to the Name Server which converts it to an IP Address(like 12.34.56.78). This is then sent to the respective server for further processing. The figure below shows how exactly this happens. Syntax The syntax for including the DNS module in our node application is – const dns = require(‘dns’) DNS methods and its descriptionsWe will look into a real example and some important DNS methods. Let us setup a basic node application by giving the command npm init -y in terminal, inside a folder. I had created an empty NodeJS folder for the same. $ npm init -y Wrote to D:\NodeJS\package.json: {   "name": "NodeJS",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC" }The above commands create a basic package.json file, which is the basis of any Node.js project. We are using the -y option, so that we don’t have to enter the details manually. Next, open the folder in a code editor which is VSCode in my case. Here, I have created a file dns.js and the first line contains the code for importing the dns module.1. lookup()Next, we will call the dns lookup function, which takes two arguments. The first is the domain we want to lookup, which can be anything and is knowledgehut.com in our case. The second is the callback or function that we want to run, once the lookup is complete. The function that runs on completion takes two arguments. The first argument contains an error, if one occurs, and the second is the value or the IP address of the domain. So, inside our function if we have an error we are printing it in the console and returning, which means no further code will run. If we don’t have an error, we are printing the value. Add the below code in a dns.js file.const dns = require('dns');  dns.lookup('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) To run this, I am opening the Integrated terminal, which comes in VSCode by pressing Ctrl+J on Windows or Cmd+J on Mac. Here, give the command node dns to run our file dns.js. The output of the same is below. 54.147.15.161When we run this program, we are not getting any error and getting the IP address of the domain name. 2. resolve()The function resolve() is pretty much identical to the lookup() function. Our code remains the same and we have only changed the lookup to resolve. Add the below code in a dns.js file.const dns = require('dns');  dns.resolve('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) We can get the output by running node dns command from terminal.[ '34.236.195.104',   '50.16.1.247',       '54.147.15.161',     '3.223.64.88' ]But as we can see from the output, we got all the IP addresses associated with this domain.The resolve function actually goes and makes a network request to the DNS system, to see how many IP addresses are registered with that domain name. The lookup function actually just uses the computer’s internal mechanism first to see if there is an IP address that it can return without having to do a network request. So, resolve function is more accurate and should be used in production as it gives all the IP addresses associated with the domain. You can also provide another argument to the resolve function to specify what type of record you want to look up. For example, with the DNS system you can find the Mail exchange record of the domain. This record handles the request, when you send an email to the domain, and specifies which server should handle the request.So, in our code we will add MX as the second argument. Add the below code in a dns.js file.const dns = require('dns'); dns.resolve('knowledgehut.com', 'MX', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); })On running the node dns command from the Integrated Terminal again, we are getting the information of the Mail exchange of that domain in an array.[ { exchange: 'mail.knowledgehut.com', priority: 0 } ]  3. reverse() Now, we will look into the reverse function. It works exactly the same as lookup() and resolve(), but instead of supplying a domain name, we are supplying an IP address. This function goes into the DNS system, to find out if there are any reverse records associated with this IP address. We are using 8.8.8.8, which is the publicly available IP address for Google. Add the below code in a dns.js file. const dns = require('dns');  dns.reverse('8.8.8.8', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) On running the node dns again, we will get the reverse record within an array. [ 'dns.google' ]  4. lookUp Service() This can be used to get the information of host, which includes the hostname and the service. We need to provide a valid IP address and a valid Port as arguments. It uses the Operating Systems getnameinfo to get this data. If the IP address or the Port are not valid, a TypeError will be thrown.   In our example, we are providing a known IP address along with the port 587. This port is used for Mail Exchange(MX).  Then we are console logging the host and service. Add the below code in a dns.js file. const dns = require('dns'); dns.lookupService('34.236.195.104', 587, (err, host, service) => {     if(err) {         console.log(err);         return;     }     console.log(host,'\n', service); })It is shown in console on running node dns in Integrated Terminal.ec2-34-236-195-104.compute-1.amazonaws.com    5875. resolve4()The resolve4 method is almost similar to the resolve() method. It also returns an array of IP addresses, but only the IPv4 addresses and not the newer IPv6 addresses. Still most of the websites use IPv4 address and this function will give a valid output. Add the below code in a dns.js file.const dns = require('dns');  dns.resolve4('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. [ '50.16.1.247',       '54.147.15.161',     '34.236.195.104',    '3.223.64.88' ] 6. resolve6()The IPv4 is a 32 bit address, developed in the 90s. But since there are only 4 billion addresses, the world ran out and they were all used up. So, IPv6 was invented and since then many websites have this new IPv6 address. The resolve6() method internal mechanism is also like the resolve() method, but it only returns array of IPv6 addresses. Add the below code in a dns.js file.const dns = require('dns'); dns.resolve6('nodejs.org', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); }) It is shown in console on running node dns in Integrated Terminal.[ '2606:4700:8d75:a0e6:9d7:10c:f52a:f808' ]7. resolveMx()The resolveMx() method is used to get the Mail exchange records for a hostname. The Mail exchange records are also known as MX records. We need to pass the hostname as argument and we will receive the details in an array, if the request was successful. Add the below code in a dns.js file.const dns = require('dns'); dns.resolveMx('nodejs.org', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); })It is shown in console on running node dns in Integrated Terminal.  [ { exchange: 'aspmx.l.google.com', priority: 10 },         { exchange: 'alt1.aspmx.l.google.com', priority: 20 },    { exchange: 'alt2.aspmx.l.google.com', priority: 20 },    { exchange: 'aspmx2.googlemail.com', priority: 30 },      { exchange: 'aspmx3.googlemail.com', priority: 30 } ] 8. resolveNs() The resolveNs() method is used to get the Name Server(NS records) information of a hostname. The hostname is passed as argument and we receive the information back in an array. Add the below code in a dns.js file. const dns = require('dns');  dns.resolveNs('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. [ 'pablo.ns.cloudflare.com', 'meera.ns.cloudflare.com' ] 9. resolveSoa() The resolveSoa() method is used to get the Start of Authority record(SOA record) for a given hostname. The SOA records contain a lot of important information about the hostname like Name Server, Host Master, Expiry time. The hostname is passed as argument, and we receive all the information in an object. Add the below code in a dns.js file. const dns = require('dns');  dns.resolveSoa('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. { nsname: 'meera.ns.cloudflare.com',    hostmaster: 'dns.cloudflare.com',     serial: 2035938779,    refresh: 10000,    retry: 2400,    expire: 604800,    minttl: 3600 } 10. resolveTxt() The resolveTxt() method is used to get the txt queries(TXT records) for a given hostname. The TXT records were actually intended to put human-readable notes in DNS, by the domain administrator. But nowadays, it is also used to prevent email spam.  In the resolveTxt() method the hostname is passed as argument, but we receive the output as a two-dimensional array of text records available for that hostname. Add the below code in a dns.js file.const dns = require('dns');  dns.resolveTxt('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) The output is shown in console on running node dns in Integrated Terminal. [ [ 'v=spf1 include:aspmx.googlemail.com -all' ] ] 11. resolvePtr() The resolvePtr() method is used to get the pointer records(PTR records) for a given hostname. Now, a PTR record maps an IP address to a domain and is also called “reverse DNS entry”. It is used to convert an IP address to a domain name. This is mainly used as a security and anti-spam measure. 12. resolveNaptr() The resolveNaptr() method is used to get the Naming Authority Pointer records(NAPTR records) for a given hostname. The NAPTR records are newer type of DNS records, in which we can write in regular expressions. The NAPTR records are mostly used in applications, which support Internet Telephony. The resolveNaptr() method is useful to know, whether a domain supports SIP or some other VoIP(Voice Over IP) services. 13. resolveSrv() The resolveSrv() method is used to get the service records(SRV records) for a given hostname. The service records specify the host and port for specific services on a server like voice over IP(VoIP), instant messaging and other services. 14. setServers() The setServers() is a very important method, which is used to set the IP address and port of servers. The argument to this method, is an array of formatted array. Example for the same is below. dns.setServers([    '4.4.4.4',    '[2001:4860:4860::8888]',    '4.4.4.4:1053',    '[2001:4860:4860::8888]:1053'  ]); 15. getServers() The getServers() method of DNS is used to get all the IP addresses associated with a server. It returns the IP addresses, belonging to the server in an array. DNS promises API The dns.promises API returns promise objects, instead of the callbacks which we have seen earlier. So, they are more modern as most of the JavaScript community is moving towards promises, instead of callbacks. We need to access the promises API by using require(‘dns’).promises Almost all the methods that are in dns are also available in DNS promises API. The complete list is below. resolver.getServers() resolver.resolve() resolver.resolve4() resolver.resolve6() resolver.resolveAny() resolver.resolveCaa() resolver.resolveCname() resolver.resolveMx() resolver.resolveNaptr() resolver.resolveNs() resolver.resolvePtr() resolver.resolveSoa() resolver.resolveSrv() resolver.resolveTxt() resolver.reverse() resolver.setServers() We will look into some of the examples, along with syntaxes. 16. resolver.resolve4() This method takes the hostname as argument. On success the Promise is resolved with an array of IPv4 addresses. In the below example, we are using a different import, than our previous section.  Since, the resolver.resolve4() returns a promise we can use the modern syntax of ‘then and catch’ block. The .then is executed if the Promise resolves to success and the .error is executed if the Promise fails. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve4('geeksforgeeks.org')      .then(addresses => console.log(addresses))      .catch(err => console.log(err)) The output is shown in console on running node dns in Integrated Terminal. In the case of success, we get an array with IPv4 addresses as in our case. [ '34.218.62.116' ]  17. resolver.resolveMx() This method takes the hostname as argument. On success the Promise is resolved with an array of Mail exchange(MX records) records.  In the below example, we are using the latest async-await format for the Promise. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  (async function() {      const addresses = await resolver.resolveMx('nodejs.org');      console.log(addresses)  })() The output is shown in console on running node dns in Integrated Terminal. [ { exchange: 'alt1.aspmx.l.google.com', priority: 20 },    { exchange: 'alt2.aspmx.l.google.com', priority: 20 },    { exchange: 'aspmx2.googlemail.com', priority: 30 },      { exchange: 'aspmx3.googlemail.com', priority: 30 },      { exchange: 'aspmx.l.google.com', priority: 10 } ]18. resolver.getServers() The resolver.getServers() method returns an array of IP addresses. We can use it as below, where we are first getting the IPv6 address, by using the resolve6() method. Once, we receive it we are using it inside the .then block and it will return all the IP addresses of the server. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve6('nodejs.org')      .then(addresses => {          console.log('IPv6 is ', addresses);          console.log('Server address is ', resolver.getServers());      })      .catch(err => console.log(err)) The output is shown in the console on running node dns in Integrated Terminal. IPv6 is  [ '2606:4700:8d75:a0e6:9ca:10c:f52a:f808' ]  Server address is  [ '2405:201:3001:a3a::c0a8:1d01', '192.168.29.1' ] Error Codes A lot of errors can be thrown when we use any of the dns or dns promise methods. The errors which we can get are as below. dns.NODATA: DNS server returned answer with no data. dns.FORMERR: DNS server claims query was mis-formatted. dns.SERVFAIL: DNS server returned general failure. dns.NOTFOUND: Domain name was not found. dns.NOTIMP: DNS server does not implement requested operation. dns.REFUSED: DNS server refused the query. dns.BADQUERY: Mis formatted DNS query. dns.BADNAME: Mis formatted host name. dns.BADFAMILY: Unsupported address family. dns.BADRESP: Mis formatted DNS reply. dns.CONNREFUSED: Could not contact DNS servers. dns.TIMEOUT: Timeout happened while contacting DNS servers. dns.EOF: End of file. dns.FILE: Error reading file. dns.NOMEM: Out of memory. dns.DESTRUCTION: Channel is being destroyed. dns.BADSTR: Mis formatted string. dns.BADFLAGS: Illegal flags specified. dns.NONAME: Given host name is not numeric. dns.BADHINTS: Illegal hints flags specified. dns.NOTINITIALIZED: c-ares library initialization not yet performed. dns.LOADIPHLPAPI: Error loading iphlpapi.dll. dns.ADDRGETNETWORKPARAMS: Could not find GetNetworkParams function. dns.CANCELLED: DNS query cancelled.We will see an example of DNS error. In the below example of resolver.resolve6() method, we have given a domain name which doesn’t exist. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve6('abc.tech')      .then(addresses => console.log(addresses))      .catch(err => console.log(err)) So, we are getting the NOTFOUND error, when we are running node dns from terminal. { Error: queryAaaa ENOTFOUND abc.tech      at QueryReqWrap.onresolve [as oncomplete] (internal/dns/promises.js:163:17)    errno: 'ENOTFOUND',    code: 'ENOTFOUND',    syscall: 'queryAaaa',    hostname: 'abc.tech' } Implementation considerations There is a difference in the was dns.lookup() runs and the other dns methods like dns.resolve(), dns.reverse() runs. The dns.lookup() will always resolve a given name using the same way a ping command works. It doesn’t make a network call and is implemented as a synchronous call to getaddrinfo() function. The functions dns.resolve() and dns.reverse() are implemented quite differently, and they don’t use the getaddrinfo() function. They will always perform a DNS query on the network. So, the result is more accurate and updated. So, these differences can have significant consequences to our NodeJS program and should be considered. SummaryIn this post, we have learnt about the various DNS methods available in our Node.JS. We can use these methods to get a lot of information about any host. Many of these methods need us to have network access to the required, but they can always be used for internal NodeJS codes also. Knowledge of these methods, along with network concepts are important for NodeJS application development. 
What Is the Use of DNS Module in Node.Js?
Nabendu
Nabendu

Nabendu Biswas

Author

Nabendu Biswas is a Full Stack JavaScript Developer, who has been working in the IT industry for the past 16 years and has worked for world’s top development firms, and Investment banks. He is a passionate tech blogger. He is also a tech youtuber and loves to teach people JavaScript. He is also an Apress author with three Gatsby books published. 

Posts by Nabendu Biswas

What Is the Use of DNS Module in Node.Js?

Node.js gives the provision of using different modules. In this article, we will look into the use of DNS module in Node.  What is DNS and its importance?DNS stands for Domain Name System. The main function of the DNS is to translate the IP Address, which is a numerical label assigned to your computer. IP addresses can be thought of as names of computers on a network and are used to distinguish different devices and their locations.  For example, 8.8.8.8 is one of the many public IP addresses of Google.com. So, DNS can be considered as phonebook of the Internet. When we type any address like www.example.com in our browser, that request is sent to the Name Server which converts it to an IP Address(like 12.34.56.78). This is then sent to the respective server for further processing. The figure below shows how exactly this happens. Syntax The syntax for including the DNS module in our node application is – const dns = require(‘dns’) DNS methods and its descriptionsWe will look into a real example and some important DNS methods. Let us setup a basic node application by giving the command npm init -y in terminal, inside a folder. I had created an empty NodeJS folder for the same. $ npm init -y Wrote to D:\NodeJS\package.json: {   "name": "NodeJS",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC" }The above commands create a basic package.json file, which is the basis of any Node.js project. We are using the -y option, so that we don’t have to enter the details manually. Next, open the folder in a code editor which is VSCode in my case. Here, I have created a file dns.js and the first line contains the code for importing the dns module.1. lookup()Next, we will call the dns lookup function, which takes two arguments. The first is the domain we want to lookup, which can be anything and is knowledgehut.com in our case. The second is the callback or function that we want to run, once the lookup is complete. The function that runs on completion takes two arguments. The first argument contains an error, if one occurs, and the second is the value or the IP address of the domain. So, inside our function if we have an error we are printing it in the console and returning, which means no further code will run. If we don’t have an error, we are printing the value. Add the below code in a dns.js file.const dns = require('dns');  dns.lookup('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) To run this, I am opening the Integrated terminal, which comes in VSCode by pressing Ctrl+J on Windows or Cmd+J on Mac. Here, give the command node dns to run our file dns.js. The output of the same is below. 54.147.15.161When we run this program, we are not getting any error and getting the IP address of the domain name. 2. resolve()The function resolve() is pretty much identical to the lookup() function. Our code remains the same and we have only changed the lookup to resolve. Add the below code in a dns.js file.const dns = require('dns');  dns.resolve('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) We can get the output by running node dns command from terminal.[ '34.236.195.104',   '50.16.1.247',       '54.147.15.161',     '3.223.64.88' ]But as we can see from the output, we got all the IP addresses associated with this domain.The resolve function actually goes and makes a network request to the DNS system, to see how many IP addresses are registered with that domain name. The lookup function actually just uses the computer’s internal mechanism first to see if there is an IP address that it can return without having to do a network request. So, resolve function is more accurate and should be used in production as it gives all the IP addresses associated with the domain. You can also provide another argument to the resolve function to specify what type of record you want to look up. For example, with the DNS system you can find the Mail exchange record of the domain. This record handles the request, when you send an email to the domain, and specifies which server should handle the request.So, in our code we will add MX as the second argument. Add the below code in a dns.js file.const dns = require('dns'); dns.resolve('knowledgehut.com', 'MX', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); })On running the node dns command from the Integrated Terminal again, we are getting the information of the Mail exchange of that domain in an array.[ { exchange: 'mail.knowledgehut.com', priority: 0 } ]  3. reverse() Now, we will look into the reverse function. It works exactly the same as lookup() and resolve(), but instead of supplying a domain name, we are supplying an IP address. This function goes into the DNS system, to find out if there are any reverse records associated with this IP address. We are using 8.8.8.8, which is the publicly available IP address for Google. Add the below code in a dns.js file. const dns = require('dns');  dns.reverse('8.8.8.8', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) On running the node dns again, we will get the reverse record within an array. [ 'dns.google' ]  4. lookUp Service() This can be used to get the information of host, which includes the hostname and the service. We need to provide a valid IP address and a valid Port as arguments. It uses the Operating Systems getnameinfo to get this data. If the IP address or the Port are not valid, a TypeError will be thrown.   In our example, we are providing a known IP address along with the port 587. This port is used for Mail Exchange(MX).  Then we are console logging the host and service. Add the below code in a dns.js file. const dns = require('dns'); dns.lookupService('34.236.195.104', 587, (err, host, service) => {     if(err) {         console.log(err);         return;     }     console.log(host,'\n', service); })It is shown in console on running node dns in Integrated Terminal.ec2-34-236-195-104.compute-1.amazonaws.com    5875. resolve4()The resolve4 method is almost similar to the resolve() method. It also returns an array of IP addresses, but only the IPv4 addresses and not the newer IPv6 addresses. Still most of the websites use IPv4 address and this function will give a valid output. Add the below code in a dns.js file.const dns = require('dns');  dns.resolve4('knowledgehut.com', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. [ '50.16.1.247',       '54.147.15.161',     '34.236.195.104',    '3.223.64.88' ] 6. resolve6()The IPv4 is a 32 bit address, developed in the 90s. But since there are only 4 billion addresses, the world ran out and they were all used up. So, IPv6 was invented and since then many websites have this new IPv6 address. The resolve6() method internal mechanism is also like the resolve() method, but it only returns array of IPv6 addresses. Add the below code in a dns.js file.const dns = require('dns'); dns.resolve6('nodejs.org', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); }) It is shown in console on running node dns in Integrated Terminal.[ '2606:4700:8d75:a0e6:9d7:10c:f52a:f808' ]7. resolveMx()The resolveMx() method is used to get the Mail exchange records for a hostname. The Mail exchange records are also known as MX records. We need to pass the hostname as argument and we will receive the details in an array, if the request was successful. Add the below code in a dns.js file.const dns = require('dns'); dns.resolveMx('nodejs.org', (err, value) => {     if(err) {         console.log(err);         return;     }     console.log(value); })It is shown in console on running node dns in Integrated Terminal.  [ { exchange: 'aspmx.l.google.com', priority: 10 },         { exchange: 'alt1.aspmx.l.google.com', priority: 20 },    { exchange: 'alt2.aspmx.l.google.com', priority: 20 },    { exchange: 'aspmx2.googlemail.com', priority: 30 },      { exchange: 'aspmx3.googlemail.com', priority: 30 } ] 8. resolveNs() The resolveNs() method is used to get the Name Server(NS records) information of a hostname. The hostname is passed as argument and we receive the information back in an array. Add the below code in a dns.js file. const dns = require('dns');  dns.resolveNs('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. [ 'pablo.ns.cloudflare.com', 'meera.ns.cloudflare.com' ] 9. resolveSoa() The resolveSoa() method is used to get the Start of Authority record(SOA record) for a given hostname. The SOA records contain a lot of important information about the hostname like Name Server, Host Master, Expiry time. The hostname is passed as argument, and we receive all the information in an object. Add the below code in a dns.js file. const dns = require('dns');  dns.resolveSoa('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) It is shown in console on running node dns in Integrated Terminal. { nsname: 'meera.ns.cloudflare.com',    hostmaster: 'dns.cloudflare.com',     serial: 2035938779,    refresh: 10000,    retry: 2400,    expire: 604800,    minttl: 3600 } 10. resolveTxt() The resolveTxt() method is used to get the txt queries(TXT records) for a given hostname. The TXT records were actually intended to put human-readable notes in DNS, by the domain administrator. But nowadays, it is also used to prevent email spam.  In the resolveTxt() method the hostname is passed as argument, but we receive the output as a two-dimensional array of text records available for that hostname. Add the below code in a dns.js file.const dns = require('dns');  dns.resolveTxt('nodejs.org', (err, value) => {      if(err) {          console.log(err);          return;      }      console.log(value);  }) The output is shown in console on running node dns in Integrated Terminal. [ [ 'v=spf1 include:aspmx.googlemail.com -all' ] ] 11. resolvePtr() The resolvePtr() method is used to get the pointer records(PTR records) for a given hostname. Now, a PTR record maps an IP address to a domain and is also called “reverse DNS entry”. It is used to convert an IP address to a domain name. This is mainly used as a security and anti-spam measure. 12. resolveNaptr() The resolveNaptr() method is used to get the Naming Authority Pointer records(NAPTR records) for a given hostname. The NAPTR records are newer type of DNS records, in which we can write in regular expressions. The NAPTR records are mostly used in applications, which support Internet Telephony. The resolveNaptr() method is useful to know, whether a domain supports SIP or some other VoIP(Voice Over IP) services. 13. resolveSrv() The resolveSrv() method is used to get the service records(SRV records) for a given hostname. The service records specify the host and port for specific services on a server like voice over IP(VoIP), instant messaging and other services. 14. setServers() The setServers() is a very important method, which is used to set the IP address and port of servers. The argument to this method, is an array of formatted array. Example for the same is below. dns.setServers([    '4.4.4.4',    '[2001:4860:4860::8888]',    '4.4.4.4:1053',    '[2001:4860:4860::8888]:1053'  ]); 15. getServers() The getServers() method of DNS is used to get all the IP addresses associated with a server. It returns the IP addresses, belonging to the server in an array. DNS promises API The dns.promises API returns promise objects, instead of the callbacks which we have seen earlier. So, they are more modern as most of the JavaScript community is moving towards promises, instead of callbacks. We need to access the promises API by using require(‘dns’).promises Almost all the methods that are in dns are also available in DNS promises API. The complete list is below. resolver.getServers() resolver.resolve() resolver.resolve4() resolver.resolve6() resolver.resolveAny() resolver.resolveCaa() resolver.resolveCname() resolver.resolveMx() resolver.resolveNaptr() resolver.resolveNs() resolver.resolvePtr() resolver.resolveSoa() resolver.resolveSrv() resolver.resolveTxt() resolver.reverse() resolver.setServers() We will look into some of the examples, along with syntaxes. 16. resolver.resolve4() This method takes the hostname as argument. On success the Promise is resolved with an array of IPv4 addresses. In the below example, we are using a different import, than our previous section.  Since, the resolver.resolve4() returns a promise we can use the modern syntax of ‘then and catch’ block. The .then is executed if the Promise resolves to success and the .error is executed if the Promise fails. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve4('geeksforgeeks.org')      .then(addresses => console.log(addresses))      .catch(err => console.log(err)) The output is shown in console on running node dns in Integrated Terminal. In the case of success, we get an array with IPv4 addresses as in our case. [ '34.218.62.116' ]  17. resolver.resolveMx() This method takes the hostname as argument. On success the Promise is resolved with an array of Mail exchange(MX records) records.  In the below example, we are using the latest async-await format for the Promise. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  (async function() {      const addresses = await resolver.resolveMx('nodejs.org');      console.log(addresses)  })() The output is shown in console on running node dns in Integrated Terminal. [ { exchange: 'alt1.aspmx.l.google.com', priority: 20 },    { exchange: 'alt2.aspmx.l.google.com', priority: 20 },    { exchange: 'aspmx2.googlemail.com', priority: 30 },      { exchange: 'aspmx3.googlemail.com', priority: 30 },      { exchange: 'aspmx.l.google.com', priority: 10 } ]18. resolver.getServers() The resolver.getServers() method returns an array of IP addresses. We can use it as below, where we are first getting the IPv6 address, by using the resolve6() method. Once, we receive it we are using it inside the .then block and it will return all the IP addresses of the server. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve6('nodejs.org')      .then(addresses => {          console.log('IPv6 is ', addresses);          console.log('Server address is ', resolver.getServers());      })      .catch(err => console.log(err)) The output is shown in the console on running node dns in Integrated Terminal. IPv6 is  [ '2606:4700:8d75:a0e6:9ca:10c:f52a:f808' ]  Server address is  [ '2405:201:3001:a3a::c0a8:1d01', '192.168.29.1' ] Error Codes A lot of errors can be thrown when we use any of the dns or dns promise methods. The errors which we can get are as below. dns.NODATA: DNS server returned answer with no data. dns.FORMERR: DNS server claims query was mis-formatted. dns.SERVFAIL: DNS server returned general failure. dns.NOTFOUND: Domain name was not found. dns.NOTIMP: DNS server does not implement requested operation. dns.REFUSED: DNS server refused the query. dns.BADQUERY: Mis formatted DNS query. dns.BADNAME: Mis formatted host name. dns.BADFAMILY: Unsupported address family. dns.BADRESP: Mis formatted DNS reply. dns.CONNREFUSED: Could not contact DNS servers. dns.TIMEOUT: Timeout happened while contacting DNS servers. dns.EOF: End of file. dns.FILE: Error reading file. dns.NOMEM: Out of memory. dns.DESTRUCTION: Channel is being destroyed. dns.BADSTR: Mis formatted string. dns.BADFLAGS: Illegal flags specified. dns.NONAME: Given host name is not numeric. dns.BADHINTS: Illegal hints flags specified. dns.NOTINITIALIZED: c-ares library initialization not yet performed. dns.LOADIPHLPAPI: Error loading iphlpapi.dll. dns.ADDRGETNETWORKPARAMS: Could not find GetNetworkParams function. dns.CANCELLED: DNS query cancelled.We will see an example of DNS error. In the below example of resolver.resolve6() method, we have given a domain name which doesn’t exist. Add the below code in a dns.js file. const { Resolver } = require('dns').promises;  const resolver = new Resolver();  resolver.resolve6('abc.tech')      .then(addresses => console.log(addresses))      .catch(err => console.log(err)) So, we are getting the NOTFOUND error, when we are running node dns from terminal. { Error: queryAaaa ENOTFOUND abc.tech      at QueryReqWrap.onresolve [as oncomplete] (internal/dns/promises.js:163:17)    errno: 'ENOTFOUND',    code: 'ENOTFOUND',    syscall: 'queryAaaa',    hostname: 'abc.tech' } Implementation considerations There is a difference in the was dns.lookup() runs and the other dns methods like dns.resolve(), dns.reverse() runs. The dns.lookup() will always resolve a given name using the same way a ping command works. It doesn’t make a network call and is implemented as a synchronous call to getaddrinfo() function. The functions dns.resolve() and dns.reverse() are implemented quite differently, and they don’t use the getaddrinfo() function. They will always perform a DNS query on the network. So, the result is more accurate and updated. So, these differences can have significant consequences to our NodeJS program and should be considered. SummaryIn this post, we have learnt about the various DNS methods available in our Node.JS. We can use these methods to get a lot of information about any host. Many of these methods need us to have network access to the required, but they can always be used for internal NodeJS codes also. Knowledge of these methods, along with network concepts are important for NodeJS application development. 
9283
What Is the Use of DNS Module in Node.Js?

Node.js gives the provision of using different mo... Read More

What Is the Relationship Between Node.Js and V8?

In this article, we will look into Node.js and V8. Node.js is a very important part of the JavaScript ecosystem, as it is used in the backend to produce a complete application. It is often considered a part of the popular MERN(MongoDB, ExpressJS, ReactJS and Node.js) stack and MEAN (MongoDB, ExpressJS, Angular and Node.js) stack. The V8 engine is what powers Node.js and it is an open-source engine on which even Chrome works. It parses and runs your JavaScript inside a Node environment. Overview on Node.jsNode.js was created by Ryan Dahl in 2009 and since then it has become a very popular backend technology. Till then the backend was dominated by languages like PHP, ASP.NET and Java. It has become popular because it enables a Frontend developer with JavaScript skills to easily create full stack apps.The formal definition on the official Node.js website describes Node.js as “a JavaScript runtime built on Chrome’s V8 JavaScript engine.”Node.js came into existence when its creator Ryan Dahl, understanding the power of V8, powered the Chrome browser and extended it so that it can run on your machine as a standalone application. Another part of the definition on the official Node.js website says,Node.js uses an event driven, non-blocking I/O model that makes it lightweight and efficient.I/O refers to input/output and this is where the additional functionality of Node.js comes into play. We can read and edit local files in Node.js and also do an HTTP request to an API. The earlier backend systems like PHP and ASP used to block the program till a network request was complete. But it was completely changed by Node.JS, which sends the request and then goes to the next line of code. So, it is non-blocking and faster than the earlier backend technologies. But it is a single-threaded technology and that is where it has some limitations, whereas Java shines because of it being multi-threaded. Yet another part of the official definition on the Node.js website says,Node.js package ecosystem, npm is the largest ecosystem of open-source libraries in the world. Over the past decade, an amazing community of open-source enthusiasts have created more than 1 million npm packages, which enhance the capabilities of Node.js.It is completely open-source and anyone can use it, as it has an MIT licence, for developing server-side and networking applications. It can run on all three Operating Systems i.e., Mac OS, Windows, and Linux.Overview on V8 JavaScript engineV8 is Google’s open-source JavaScript engine, which is written in C++. It was developed in 2008 for Google Chrome and Chromium based browsers (like Brave), but was used to build Node.js for server-side coding. In fact, the V8 engine, is also used by JSON based No-SQL databases like Couchbase and the popular MongoDB. Besides this, V8 also powers the popular desktop application framework Electron and the latest server-side runtime environment of Deno. V8 is a JavaScript engine, because it takes our JavaScript and executes it while browsing in Chrome. It actually provides a runtime environment in which JavaScript executes. The great thing about this is that the JavaScript engine is independent of the browser in which it executes. This is the feature that prompted the creator of Node.JS to choose V8 engine to power Node.JS and the rest is history. The popularity of Node.JS exploded and the V8 engine was also used to create desktop frameworks and databases.There are other JavaScript engines like SpiderMonkey used by Firefox, and JavaScript Core used by Safari. Microsoft’s Edge was originally based on Chakra JavaScript engine, but has been recently re-built with Chromium and V8 engine.How V8 Engine works A JavaScript Engine is an interpreter which executes JavaScript code. We can create JavaScript engine in two ways – the first way is to implement as a standard interpreter which is done by SpiderMonkey from Mozilla. The other way is the Just-in-time (JIT) compilation, which converts the native JavaScript code to machine code and that is the way V8 uses it. So, the difference between V8 code and others is that it does not produce any intermediate code. When a developer or program runs a JavaScript on V8(i.e. in browser or Node environment), the Ignition interpreter compiles the JavaScript code and generates non-optimized machine code. On runtime, the machine code is analyzed and re-compiled for best performance, by the Turbofan and Crankshaft components of V8. The V8 engine also uses some other components, along with the ones we had seen above. They are Liftoff and Orinoco– Liftoff is responsible for machine code generation in a highly optimized way. It generates code for each opcode and perform way better then Turbofan.Orinoco is responsible for garbage collection. It looks for disconnected memory allocations and perform operations to free up more space. It also update the pointers to new memory locations.V8 also uses a lot of different threads and they are – The primary thread fetches and compiles the JavaScript code.There is another thread which is used to optimize the running code, while the primary thread continues its execution. Yet another thread is used for profiling, which tells on runtime the methods that are needed to be optimized. Some of the threads also do garbage collection.The Just-in-Time ParadigmWe will learn a bit more about the Just-in-Time (JIT) compilation in V8. For a code to execute in any programming language, it must be converted into machine code, which the computer understands. There is a different paradigm for this transformation. Most of the traditional languages created before JavaScript like C++ and Java, perform something called Ahead-of-Time compilation. Here, the code is transformed into machine code before the execution of our program during compile time. Anyone who has worked with Java or C++ knows that we run commands like below to compile a Java or C++ program.javac MyJavaProgram.java  g++ -o mycppprogram mycppprogram.cpp This converts the code into machine code after which we can run our program with commands like below.  java MyJavaProgram  ./mycppprogram On the other hand, in languages like JavaScript and Python, each line of code is executed at runtime. This is done because it is impossible to know the exact code before execution. In a browser, you never compile a code first and then run it, because it is done automatically behind the scenes.So, the Ahead-of-Time compilation produces more optimized and fast code, because of the compilation done before hand. Which is why interpretation done by languages like JavaScript are slower.To overcome this problem in dynamic languages, the approach of Just-in-Time (JIT) compilation, was created, which combines the best of both interpretation and compilation. So, an interpretation step runs before the compilation step, where the V8 engine detects the more frequently used functions and code and compiles them using information from previous executions.During compile time, this code is re-compiled for optimal performance.What is the relationship between Node and V8?The Node.js is referred to as a runtime environment, which includes everything you need to run a program written in JavaScript.The core powering Node.js is this V8 engine. The diagram shows a comparison with the Java Virtual Machine (JVM), which power the Java Runtime environment. Beside the V8 engine the Node.js runtime environment adds many Node APIs to power the Node.js environment. We can also extend the functionality of our node code by installing additional npm packages.One thing to understand is that V8 is essentially an independent C++ library, that is used by Node or Chromium to run JavaScript code. V8 exposes an API that other code can use, so if you have your own C++ program, you can embed V8 in it and run a JavaScript program. That is how it is done by Node and Chrome.Suppose, we want to add a functionality in our JavaScript code to have statements like print(‘hello world’), in addition to the console.log(‘Hello World’). We can add our own implementation of print function in C++, in V8, which is anyway open sourced. Can Node.js work without V8?The current Node.js engine cannot work without V8. It would have no JavaScript engine and hence no ability to run any JavaScript code. The fact is that the native code bindings, which come with Node.js like the fs module and the Net module, rely on the V8 interface between C++ and JavaScript.  Although in the tech world everything is possible and Microsoft in July 2016, made an effort to use Chakra JavaScript engine (which was used in Edge browser at that time) in Node.js and replace the V8 engine,  that project never took off and Microsoft Edge itself recently moved to Chromium, which uses V8 JavaScript engine.The new kid on the block for server-side programming is DENO. Many consider that it could be a replacement to Node.js in the next 2-3 years, and it also uses V8 JavaScript engine under its hood.Summary We have got an overview of Node.js runtime environment and V8 JavaScript engine in this post. Then, we have gone through the working of the V8 engine. We also investigated details of the Just-in-Time compilation, used by V8 JavaScript engine. Also, we have understood the relationship between Node.js and V8 engine and how V8 engine is independent of Node.js.Lastly, we have learnt that it is not possible for Node.js to run without a JavaScript engine like V8. It can, however, be replaced by another JavaScript engine like Chakra from Microsoft; even though this is highly improbable,  it is still possible. 
5640
What Is the Relationship Between Node.Js and V8?

In this article, we will look into Node.js and ... Read More

What is query string in Node.js?

In this article, we will look into query string module in Node.js, and understand a few methods to deal with query string. The available methods can be used to convert query string into a JSON object and convert a JSON object into query string.What is Query StringA query string according to Wikipedia is a part of the uniform resource locator (URL), that assigns values to specified parameters. In plain English it is the string after the ? in a url. Some url examples are shown below.https://example.com/over/there?name=ferret https://example.com/path/to/page?name=ferret&color=purpleThe query string in first case is name=ferret and in second case is name=ferret&color=purpleNode.js Query string moduleNow, the Node.js query string module provides methods for parsing and formatting URL query strings. The query string module can be accessed using the below –const querystring = require(‘querystring’)We will now look into the below six methods in the next section.querystring.decode()querystring.encode()querystring.escape(str)querystring.parse(str[, sep[, eq[, options]]])querystring.stringify(obj[, sep[, eq[, options]]])querystring.unescape(str)Query String methods with descriptionLet us look into a real example to understand the important Query string methods. Let us setup a basic Node application by giving the command npm init -y in terminal, inside a folder. I had created an empty NodeJS folder for the same.$ npm init -y Wrote to D:\NodeJS\package.json: {   "name": "NodeJS",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC" }The above commands create a basic package.json file, which is the basis of any Node.js project. We are using the -y option, so that we don’t have to enter the details manually.Next, open the folder in a code editor which is VSCode in my case. Here, I have created a file querystring.js and the first line contains the importing of querystring module.querystring.parse() MethodThe querystring.parse() method is used to parse the URL query string into an object that contains the key value pair. The object which we get is not a JavaScript object, so we cannot use Object methods like obj.toString, or obj.hasOwnProperty().The latest UTF-8 encoding format is assumed unless we specify a different encoding format. But we should stick to UTF-8 encoding as it is the standard and contains all international characters like the Chinese characters and the hindi characters. After that also if we need alternative character encoding, then the decodeURIComponent option should be used.The syntax for the method is below.querystring.parse( str[, sep[, eq[, options]]]) )As seen from the above syntax the method accepts four parameters, and they are described below.str: This is the only required string field and it specifies the query string that has to be parsed.sep: It is an optional string field, which if given specifies the substring used to delimit the key and value pairs in the query string. The default value which is generally used is “&”.eq: It is an optional string field that specifies the substring used to delimit keys and values in the query string. The default value which is generally used is “=”.options: It is an optional object field which is used to modify the behaviour of the method. It can have the following parameters:decodeURIComponent: It is a function that would be used to specify the encoding format in the query string. The default value is querystring.unescape(), about which we will learn later.maxKeys: It is the number which specifies the maximum number of keys that should be parsed. A value of “0” would remove all the counting limits, and it can parse any number of keys. The default value is set at “1000”.The below example shows the various options used in querystring.parse() method. Add the below code in querystring.js file, which we created earlier.// Import the querystring module const querystring = require("querystring");   // Specify the URL query string to be parsed   let urlQueryString = "name=nabendu&units=kgs&units=pounds&login=false";   // Use the parse() method on the string   let parsedObj = querystring.parse(urlQueryString);   console.log("Parsed Query 1:", parsedObj);   // Use the parse() method on the string with sep as `&&` and eq as `-` urlQueryString = "name-nabendu&&units-kgs&&units-pounds&&login-true"; parsedObj = querystring.parse(urlQueryString, "&&", "-");   console.log("\nParsed Query 2:", parsedObj); // Specify a new URL query string to be parsed   urlQueryString = "type=admin&articles=java&articles=javascript&articles=kotlin&access=true"; // Use the parse() method on the string with maxKeys set to 1   parsedObj = querystring.parse(urlQueryString, "&", "=", { maxKeys: 1 });   console.log("\nParsed Query 3:", parsedObj);   // Use the parse() method on the string with maxKeys set to 2   parsedObj =  querystring.parse(urlQueryString, "&", "=", { maxKeys: 2 });   console.log("\nParsed Query 4:", parsedObj); // Use the parse() method on the string with maxKeys set to 0 (no limits) parsedObj = querystring.parse(urlQueryString, "&", "=", { maxKeys: 0 }); console.log("\nParsed Query 5:", parsedObj);Now, run the command node querystring.js from the Integrated terminal in VSCode or any terminal. Note that you need to be inside the folder NodeJS, which we had created earlier. The output of the same will be below.Parsed Query 1: [Object: null prototype] { name: 'nabendu', units: [ 'kgs', 'pounds' ], login: 'false' } Parsed Query 2: [Object: null prototype] { name: 'nabendu', units: [ 'kgs', 'pounds' ], login: 'true' } Parsed Query 3: [Object: null prototype] { type: 'admin' } Parsed Query 4: [Object: null prototype] { type: 'admin', articles: 'java' } Parsed Query 5: [Object: null prototype] {   type: 'admin',   articles: [ 'java', 'javascript', 'kotlin' ],   access: 'true' }querystring.stringify() MethodThe querystring.stringify() method is used to produce a query string from a given object, which contains a key value pair. It is exactly the opposite of querystring.parse() Method.It can be used to convert the string, numbers and Boolean values for the key. You can also use an array of string, numbers or Boolean as values. This method of changing an object to query string is called serialized.The latest UTF-8 encoding format is assumed unless we specify a different encoding format. But we should stick to UTF-8 encoding as it is the standard and contains all international characters like the Chinese characters and the Hindi characters. If we still need an alternative character encoding, then the decodeURIComponent option should be used.Syntax for the method is below.querystring. stringify( obj[, sep[, eq[, options]]]) )As from the above syntax the method accepts four parameters, and they are described below.obj: This is the only required object field and it specifies the object that has to be serialized.sep: It is an optional string field, which if given specifies the substring used to delimit the key and value pairs in the query string. The default value which is generally used is “&”.eq: It is an optional string field that specifies the substring used to delimit keys and values in the query string. The default value which is generally used is “=”.options: It is an optional object field which is used to modify the behaviour of the method. It can have the following parameters:decodeURIComponent: It is a function that would be used to specify the encoding format in the query string. The default value is querystring.escape(), about which we will learn later.The below example shows the various options used in querystring.stringify() method. Add the below code in querystring.js file, which we created earlier.// Import the querystring module   const querystring = require("querystring");   // Specify the object that needed to be serialized   let obj = {   name: "nabendu",   access: true,   role: ["developer", "architect", "manager"],   };   // Use the stringify() method on the object   let queryString = querystring.stringify(obj);   console.log("Query String 1:", queryString);   obj = {       name: "Parag",       access: false,       role: ["editor", "HR"],   };   // Use the stringify() method on the object with sep as `, ` and eq as `:` queryString = querystring.stringify(obj, ", ", ":");   console.log("Query String 2:", queryString);   // Use the stringify() method on the object with sep as `&&&` and eq as `==`   queryString = querystring.stringify(obj, "&&&", "==");   console.log("\nQuery String 3:", queryString);Now, run the command node querystring.js from the Integrated terminal in VSCode or any terminal. Note that you need to be inside the folder NodeJS, which we had created earlier. The output of the same will be below.Query String 1: name=nabendu&access=true&role=developer&role=architect&role=managerQuery String 2: name:Parag, access:false, role:editor, role:HR        Query String 3: name==Parag&&&access==false&&&role==editor&&&role==HRquerystring.decode() MethodThe querystring.decode() method is nothing but an alias for querystring.parse() method. In our parse example, we can use it. So, add the below code in querystring.js file, which we created earlier.// Import the querystring module const querystring = require("querystring");   // Specify the URL query string to be parsed   let urlQueryString = "name=nabendu&units=kgs&units=pounds&login=false";   // Use the parse() method on the string   let parsedObj = querystring.decode(urlQueryString); console.log("Parsed Query 1:", parsedObj);As earlier, run the command node querystring.js from a terminal. And the output will be same as that with querystring.parse() method.Parsed Query 1: [Object: null prototype] { name: 'nabendu', units: [ 'kgs', 'pounds' ], login: 'false' }querystring.encode() MethodThe querystring.encode() method is nothing but an alias for querystring.stringify() method. In our stringify example, we can use it. So, add the below code in querystring.js file, which we created earlier.// Import the querystring module   const querystring = require("querystring");   // Specify the object that needed to be serialized let obj = { name: "nabendu", access: true,   role: ["developer", "architect", "manager"],   };   // Use the stringify() method on the object   let queryString = querystring.encode(obj);   console.log("Query String 1:", queryString);As earlier run the command node querystring.js from a terminal. And the output will be same as that with querystring.stringify() method.Query String 1: name=nabendu&access=true&role=developer&role=architect&role=managerquerystring.escape(str) MethodThe querystring.escape() method is used by querystring.stringify() method and is generally not used directly.querystring.unescape(str) MethodThe querystring.unescape() method is used by querystring.parse() method and is generally not used directly. SummaryIn this article we learnt about the useful query string module in Node.js, which is mainly used to parse URL query strings into Object format and also to change an object to URL query strings.
3468
What is query string in Node.js?

In this article, we will look into query string mo... Read More