Menu

Using JavaScript to Identify Whether a Server Exists

Recently, for reasons I’m sure I’ll write about in the future, I needed to find a way to use JavaScript to test if either of two web-locations are accessible – my home intranet (which would mean the user is on my network), or the corporate intranet of the company for which I work (which would mean the user is on my organization’s network). The page doing this test is on the public web.

My solution for doing this test was simple. Since neither resource is accessible publicly I put a small JavaScript file on each, then I use AJAX and jQuery to try and fetch it. If that’s successful, I know the user has access to whichever intranet site served the request and my page can react accordingly.

If neither request is successful I don’t have to do anything, but the user doesn’t see any errors unless they choose to take a look in the browser console.

image

This all worked wonderfully until I enabled SSL on the page that needs to run these tests, then it immediately fell apart.

image

Both requests fail, because a page served over HTTPS is blocked from asynchronously fetching content over an insecure connection. Which makes sense, but really throws a spanner into the works for me: neither my home nor corporate intranet sites are available outside the confines of their safe networks, so neither support HTTPS.

My first attempt at getting around this was to simply change the URL prefix for each from http:// to https:// and see what happened. Neither site supports that protocol, but is the error that comes back different for a site which exists but can’t respond, vs. a site which doesn’t exist? It appears so!

image

Sadly, my joy at having solved the problem was extremely short lived. The browser can tell the difference and reports as much in the console, but JavaScript doesn’t have access to the error reported in the console. As far as my code was concerned, both scenario was still identical with a HTTP response code of 0 and the status description worryingly generic “error.”

We are getting closer to the solution I landed on, however. The next thing I tried was specifying the port in the URL. I used the https:// prefix to avoid the “mixed content” error, but appended :80 after the hostname to specify a port that the server was actually listening on.

image

This was what I was looking for. Neither server is capable of responding to a HTTPS request on port 80, but the server that doesn’t exist immediately returns an error (with a status code of 0 and the generic “error” as the descriptive text), but the server that is accessible simply doesn’t respond. Eventually the request times out with a status code of 0 but a status description, crucially, of “timeout.”

From that, I built my imperfect but somewhat workable solution. I fire a request off to each address, both of which are going to fail. One fails immediately which indicates the server doesn’t exist, and the other times-out (which I can check for in my JavaScript), indicating that the server exists and I can react accordingly.

It’s not a perfect solution. I set the timeout limit in my code to five seconds, which means a “successful” result can’t possibly come back in less time than that. I’d like to reduce that time, but when I originally had it set at 2.5 seconds I was occasionally getting a false-positive on my corporate network caused by, y’know, an actual timeout from a request that took longer than that to return in an error state.

Nevertheless if you have a use-case like mine and you need to test whether a server exists from the client perspective (i.e. the response from doing the check server-side is irrelevant), I know of no other way. As for me, I’m still on the lookout for a more elegant design. I’m next going to try and figure out a reliable way to identify if the user is connected to my home or corporate network based on their IP address. That way I can do a quick server-side check and return an immediate result.

It’s good to have this to fall back on, though, and for now at least it appears to be working.

Comments & Discussion