Fetch request to https:www.google.com fails (obviously) with CORS

Viewed 1583

My usecase : I am trying to make a simple fetch GET request to https://www.google.com to check for the internet connectivity. I need to check the response code and depending upon that, decide if user is having internet connectivity. Now though I can see a 200 code (with no response headers or response) in the developer tools, the fetch always fails landing into the error handler for the fetch call and the console flags the CORS error.

I do understand since I am making a cross origin request so this should lead to CORS error.

I want to know what can I do to get my connectivity code working. I can't obviously alter google.com's response headers. The reason for using google.com for this is because of it's reliability, just like we hit google.com in browser mostly to check if internet is working or not :D

My code :

networkMonitor: () => {
      const headers = new Headers();
      headers.append('Cache-Control', 'no-cache');
      const timerId = setInterval(() => {
        fetch('https://www.google.com')
          .then((response) => {
            if (response.status != 200) {
               // Yay ! connected
            }
          }, (err) => {
            console.log("error: " + err); // (currently fetch failed)
          })
      }, 5000);
    }

P.S : I know there is no way to disable the same origin policy or force the other site to send the allow all origin headers. This can though be bypassed by using a cors proxy. I want to know that can google.com or similar readily available sites be used to verify connectivity by my way or not, and if not, then is there some other way to deal with them from the point of view of just getting connectivity information.

5 Answers

You can add some parameters to your fetch request with its init object. With the mode property set to no-cors, you can send GET and HEAD requests to the URL but you cannot access the response.

networkMonitor: () => {
  const headers = new Headers();
  headers.append('Cache-Control', 'no-cache');
  const timerId = setInterval(() => {
    fetch('https://www.google.com', {
      mode: 'no-cors'
    })
    .then((response) => {
      if (response.status != 200) {
        console.log('Yay ! connected')
      }
    }, (err) => {
      console.log('error: ' + err); 
  }, 5000);
}

Also, I would consider sending a HEAD request since you don't want to use the response body

You may use https://developer.mozilla.org/en-US/docs/Web/API/Request/mode to set the mode to 'no-cors'. This worked for me. It also might be enough to use a HEAD request instead of a GET to save bandwith.

Be aware of this sentence in the documentation for 'no-cors':

JavaScript may not access any properties of the resulting Response

In my tests here the response object is simply empty. A check on response.status or response.ok fails.

fetch('https://www.google.com', {
    method: 'HEAD',
    mode: 'no-cors'
  })
  .then((response) => {
    console.log("connected");
  }, (err) => {
    console.log("error: " + err); // (currently fetch failed)
  })

You can use offline.js for this task. It has different ways to check connection status.

Offline.check(): Check the current status of the connection.

Offline.state: The current state of the connection 'up' or 'down'

Please note that this repo is not maintained properly.

github link is here

As an alternative you can use CDN links with disabled cors. Like:

fetch("https://code.jquery.com/jquery-2.2.4.min.js")
    .then(x => x.text())
    .then(x => console.log(x.substring(4, 15) === "jQuery v2.2"))

I want to know that can google.com or similar readily available sites be used to verify connectivity by my way or not, and if not, then is there some other way to deal with them from the point of view of just getting connectivity information.

No, there isn't.

As you have already determined, you need CORS permission to do that.

Related