Check for internet connectivity in NodeJs
Asked Answered
O

11

51

Installed NodeJS on Raspberry Pi, is there a way to check if the rPi is connected to the internet via NodeJs ?

Outmoded answered 7/3, 2013 at 12:10 Comment(0)
M
61

A quick and dirty way is to check if Node can resolve www.google.com:

require('dns').resolve('www.google.com', function(err) {
  if (err) {
     console.log("No connection");
  } else {
     console.log("Connected");
  }
});

This isn't entire foolproof, since your RaspPi can be connected to the Internet yet unable to resolve www.google.com for some reason, and you might also want to check err.type to distinguish between 'unable to resolve' and 'cannot connect to a nameserver so the connection might be down').

Macdonald answered 7/3, 2013 at 12:48 Comment(6)
The solution depends upon google. Is there any alternate and something like a standard way?Lannielanning
@Deep if you have your own site, try to resolve it instead of google. Otherwise highly available servers like google are your best option. github.com/sindresorhus/is-online is an optionMalamute
It seems that this caches the result, so if your application lose connection after running this code it will give false impression that there is a connection.Libidinous
for connection i would go for google dns servers, so you don't rely on your isp dns resolving google, which may or may not be blocked. li 8.8.8.8Grillparzer
Doesn't work if machine already resolved google and the dns query is already cached in the machineDisarming
what about with a port? like telnet?Leventis
S
52

While robertklep's solution works, it is far from being the best choice for this. It takes about 3 minutes for dns.resolve to timeout and give an error if you don't have an internet connection, while dns.lookup responds almost instantly with the error ENOTFOUND.

So I made this function:

function checkInternet(cb) {
    require('dns').lookup('google.com',function(err) {
        if (err && err.code == "ENOTFOUND") {
            cb(false);
        } else {
            cb(true);
        }
    })
}

// example usage:
checkInternet(function(isConnected) {
    if (isConnected) {
        // connected to the internet
    } else {
        // not connected to the internet
    }
});

This is by far the fastest way of checking for internet connectivity and it avoids all errors that are not related to internet connectivity.

Surplusage answered 25/2, 2015 at 11:46 Comment(4)
Be careful with that solution! It's the one we choose to check the connectivity in our Electron app and it ends-up with a very bad suprise. dns.lookup runs on libuv's threadpool. So, for example, if you run the checkInternet through setInterval (i.e to monitor the connectivity), risks are that you may overflow the threadpool. One of the consequence is blocking all the IO in your app (since all fs operation also runs on libuv's threadpool). A good explanation herePorky
Unfortunately, this answer is incorrect. I guess there's DNS cache or something, that causes this solution to simply not work. It shows true even if I've disconnected from the internet.Patsypatt
dns.lookup() uses the operating system's DNS facilities which will cache the results, while dns.resolve() simply resolves the hostname directly.Birkenhead
@NurbolAlpysbayev do you know how to avoid the DNS cache problem?Aalto
P
18

I had to build something similar in a NodeJS-app some time ago. The way I did it was to first use the networkInterfaces() function is the OS-module and then check if one or more interfaces have a non-internal IP.

If that was true, then I used exec() to start ping with a well-defined server (I like Google's DNS servers). By checking the return value of exec(), I know if ping was sucessful or not. I adjusted the number of pings based on the interface type. Forking a process introduces some overhead, but since this test is not performed too frequently in my app, I can afford it. Also, by using ping and IP-adresses, you dont depend on DNS being configured. Here is an example:

var exec = require('child_process').exec, child;
child = exec('ping -c 1 128.39.36.96', function(error, stdout, stderr){
     if(error !== null)
          console.log("Not available")
      else
          console.log("Available")
});
Pastrami answered 7/3, 2013 at 13:13 Comment(2)
owwwh... this solutions is simple for a ping module i just discovered lately... :D Thanks @KrisChoose
Sorry to say but this isn't foolproof as a simple Firewall Rule can disable ICMP Ping not only that, depending on your ISP (internet Service Provider) by default they can enable the fact of you not being able to externally ping probe other IP Addresses, EG: Three Mobile Network by DEFAULT has their Router Devices Firewall set to not being able to Ping Probe the IP, simple fix of disabling the ICMP Ping option on the Firewall, however there used to be whats known as ICMP Cripple (D)DoS Attack simply using ICMP Ping, however thanks to advance technology of 2022, we dont have that issue anymore..Stanstance
G
11

It's not as foolproof as possible but get the job done:

var dns = require('dns');
dns.lookupService('8.8.8.8', 53, function(err, hostname, service){
  console.log(hostname, service);
    // google-public-dns-a.google.com domain
});

just use a simple if(err) and treat the response adequately. :)

ps.: Please don't bother telling me 8.8.8.8 is not a name to be resolved, it's just a lookup for a highly available dns server from google. The intention is to check connectivity, not name resolution.

Grillparzer answered 26/1, 2016 at 13:56 Comment(4)
The solution depends upon google. Is there any alternate and something like a standard way?Lannielanning
There is no such "standard" way really because in order to test for internet connectivity you have to test something actually on the internet. I suppose you could check for anything you want, amazon, isp, cdn, IDK, just used google for the sake of simplicity, BTW using the IP makes it DNS independent.Grillparzer
and the number of 53 what is that purpose for?Choose
@Choose dns port. 53 is standardGrillparzer
M
7

Here is a one liner: (Node 10.6+)

let isConnected = !!await require('dns').promises.resolve('google.com').catch(()=>{});
Mangrove answered 5/9, 2020 at 16:47 Comment(1)
this should be the accepted answer, please try thisSamurai
H
6

Since I was concerned with DNS cache in other solutions here, I tried an actual connectivity test using http2. I think this is the best way to test the internet connection as it doesn't send much data and also doesn't rely on DNS resolving alone and it is quite fast.

Note that this was added in: v8.4.0

const http2 = require('http2');

function isConnected() {
  return new Promise((resolve) => {
    const client = http2.connect('https://www.google.com');
    client.on('connect', () => {
      resolve(true);
      client.destroy();
    });
    client.on('error', () => {
      resolve(false);
      client.destroy();
    });
  });
};

isConnected().then(console.log);

Edit: I made this into a package if anyone is interested.

Heroworship answered 28/3, 2020 at 15:28 Comment(1)
This works well, responding in 58ms according to my browser console (not a rigorous test). Seems the trick is it waits for a connection and not for the page it has requested to actually load, which improves the performance. Main reason I opted for this though, it overcomes the caching issues. I added an additional setting and function though to handle timeouts: client.setTimeout(3000) client.on('timeout', () => {Hipparchus
J
4

As of 2019 you can use DNS promises lookup.

NOTE This API is experimental.

const dns = require('dns').promises;

exports.checkInternet = function checkInternet() {
    return dns.lookup('google.com')
        .then(() => true)
        .catch(() => false);
};
Jinni answered 10/4, 2019 at 18:11 Comment(1)
what about with a port? like telnet?Leventis
T
3

I found a great and simple npm tool to detect internet connection. It's looks like more reliable.

First you need to install npm i check-internet-connected

Then you can call it like follows

  const checkInternetConnected = require('check-internet-connected');

  const config = {
    timeout: 5000, //timeout connecting to each server(A and AAAA), each try (default 5000)
    retries: 5,//number of retries to do before failing (default 5)
    domain: 'google.com'//the domain to check DNS record of
  }

  checkInternetConnected(config)
    .then(() => {
      console.log("Internet available");          
    }).catch((error) => {
      console.log("No internet", error);
    });
Thrippence answered 5/4, 2019 at 13:16 Comment(3)
This seems very over-complicated compared to the other answers (which it probably just wraps around)Muntin
How complicated, But it's betterThrippence
The other answers let you check with two lines (the dns lookup service), while this requires lots more code and requires an extra module which probably does just that.Muntin
K
1

It is very helpful to check internet connection for our browser is available or not.

var internetAvailable = require("internet-available");

internetAvailable().then(function(){
    console.log("Internet available",internetAvailable);
}).catch(function(){
    console.log("No internet");
});

for more[internet-available][1]: https://www.npmjs.com/package/internet-available

Kellner answered 23/7, 2019 at 5:17 Comment(0)
S
1

It's a very simple function that does not import any stuff, but makes use of JS inbuilt function, and can only be executed when called, it does not monitor loss/internet connection; unlike some answers that make use of cache, this result is accurate as it does not return cached result.

const connected = fetch("https://google.com", {
    method: "FET",
    cache: "no-cache",
    headers: { "Content-Type": "application/json" },
    referrerPolicy: "no-referrer",
}).then(() => true)
  .catch(() => false);

call it using await(make sure your'e inside an async function or you'll get a promise)

console.log(await connected);
Samurai answered 13/11, 2020 at 13:20 Comment(1)
The question is about checking network connection in NodeJs. But you've mentioned the API used in browsers only.Shifrah
W
0
async function checkInternet() {
  const address = 'www.google.com';
  const config = {
    timeout: 100,
  };
  const probeAsync = (address) => {
    return new Promise((resolve) => {
      ping.sys.probe(address, (isAlive) => {
        resolve(isAlive);
      }, config);
    });
  };
  const isAlive = await probeAsync(address);


  return isAlive
}

ping module requires for this function

Whitening answered 23/6 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.