49

I've got a node.js app that I want to use to check if a particular site is up and returning the proper response code. I want to be able to catch any errors that come up as the domain name isn't resolving or the request is timing out. The problem is is that those errors cause Node to crap out. I'm new to this whole asynchronous programming methodology, so I'm not sure where to put my try/catch statements.

I have an ajax call that goes to something like /check/site1. Server side that calls a function which attempts to make a connection and then return the statusCode. It's a very simple function, and I've wrapped each line in a try/catch and it never catches anything. Here it is:

function checkSite(url){
    var site = http.createClient(80, url);
    var request = site.request('GET', '/', {'host': url});
    request.end();
    return request;
  }

Even with each of those lines wrapped in a try/catch, I will still get uncaught exceptions like EHOSTUNREACH and so on. I want to be able to catch those and return that to the ajax call.

Any recommendations on what to try next?

mattmcmanus
  • 1,786
  • 2
  • 18
  • 27

4 Answers4

81

http.createClient has been deprecated.

Here is a quick example of how to handle errors using the new http.request:

var http = require("http");

var options = {
    host : "www.example.com"
};

var request = http.request(options, function(req) {
    ...
});
request.on('error', function(err) {
    // Handle error
});

request.end();
Saran
  • 3,845
  • 3
  • 37
  • 59
robertjd
  • 4,723
  • 1
  • 25
  • 29
11

Unfortunately, at the moment there's no way to catch these exceptions directly, since all the stuff happens asynchronously in the background.

All you can do is to catch the uncaughtException's on your own:

var http = require('http');

function checkSite(url){
    var site = http.createClient(800, url);
    var request = site.request('GET', '/', {'host': url});
    request.end();
    return request;
}

process.on('uncaughtException', function (err) {
    console.log(err);
}); 

checkSite('http://127.0.0.1');

Which in this case (notice port 800) logs:

{ message: 'ECONNREFUSED, Connection refused',
  stack: [Getter/Setter],
  errno: 111,
  syscall: 'connect' }

Node.js is still under heavy development and there sure will be a lot of progress in the next couple of months, right now focus seem to be on fixing performance bugs for 3.x and making the API somewhat stable, because after all Node.js is mainly a server so throughput matters.

You can file a bug though, but be warned crashes etc. have way higher priority than features, and most new features make it in via fork pull requests.

Also for the current Roadmap of Node.js watch this talk by Ryan Dahl (Node's Creator):
http://developer.yahoo.com/yui/theater/video.php?v=yuiconf2010-dahl

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
  • Most informative. Answer. Ever. What you recommended is how I currently have it setup but isn't an option as I will be checking multiple sites and need the responses for each. I will look into other routes for now until better exception handling is added. That really is a bummer that those types of errors are just left floating to the top. – mattmcmanus Dec 01 '10 at 20:28
  • Well as I said in the second part of my answer, there's no way to catch it ATM. If you really need it, fork Node and add it, then do a pull requests. You won't have any luck on the issue tracker only crashes and such get attention there. – Ivo Wetzel Dec 01 '10 at 20:29
  • I wish I could fork it and add that functionality but I wouldn't even know where to start. – mattmcmanus Dec 01 '10 at 20:34
  • I'm sure this functionality will make it in in the short term, Joyent(hosting solutions) did a deal with Ryan Dahl to sponsor the development, there will be more people on the core team very soon :) – Ivo Wetzel Dec 01 '10 at 20:49
11

I stumbled across another solution while I was researching a similar problem. http.Client emits an 'error' event if a connection can't be established for any reason. If you handle this event then the exception won't be thrown:

var http = require('http');
var sys = require('sys');

function checkSite(url) {
    var site = http.createClient(80, url);
    site.on('error', function(err) {
        sys.debug('unable to connect to ' + url);
    });
    var request = site.request('GET', '/', {'host': url});
    request.end();
    request.on('response', function(res) {
        sys.debug('status code: ' + res.statusCode);
    });
}

checkSite("www.google.com");
checkSite("foo.bar.blrfl.org");

Of course, the connection error and the response to the request both arrive asynchronously, meaning that simply returning the request won't work. Instead, you'd have to notify the caller of the results from within the event handlers.

Sarah Roberts
  • 830
  • 7
  • 13
3

Actually it's even easier that the accepted answer:

function checkSite(url){
var http = require('http');
var request = http.get(url,r=>{console.log("OK",r)}).on("error",e=>{
    console.log("ERROR",e)
})
}
Zibri
  • 9,096
  • 3
  • 52
  • 44