Joe
Joe

Reputation: 8042

Exception in Node server that uses http module

Please note that the above "possible answer" questions does not contain an answer to my question. I am using require("http"). In that question the person is taking a socket input variable that they can put a handler on. I do not have the same variable.

I have a very simple server that I have written in Node.

var http = require("http");
var sys = require("sys");
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({
  target: "someServer"
});
http.createServer(function(request, response) {
    try {
      proxy.web(request,response);
    } catch (err) {
        sys.puts("I caught an error!");
    }
}).listen(5000);

When I leave my app running, it crashes. My command line says:

events.js:72

        throw er; // Unhandled 'error' event
              ^
Error: read ECONNRESET
    at errnoException (net.js:900:11)
    at TCP.onread (net.js:555:19)

It seems to crash not when server is serving files, but when it is waiting for a long time between requests.

While my code is a little more complex, I do have error catching on every callback.

Why is it crashing? What can I do?

Upvotes: 0

Views: 653

Answers (1)

josh3736
josh3736

Reputation: 145152

In node, sprinkling try and catch everywhere is not the same as catching every error. (And in most cases, doing so is useless.) Asynchronous operations cannot throw useful exceptions because control long ago left the block of code that invoked the operation.

Instead, many objects emit an error event. The error event is a special case in that node will throw a "real" exception if there are no listeners for the event. Because this exception is thrown from code you do not and cannot control (ie wrap with try/catch), it goes uncaught and the process ends.

So if you do not add an error listener to sockets, a socket error will bring down the entire app.

However, your unhandled error is not coming from your http requests. The http module adds an error handler to every socket automatically, and re-emits the error as a clientError event on the Server. Because EventEmitters only throw when the event is named error, the fact that you don't handle clientError does not matter.

If we read http-proxy's documentation, we see that it also throws an error event, and you aren't listening for it. Thus, your app dies whenever there's an error fetching something from an upstream server.

Add an error handler.

proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });
  res.end('Something went wrong.');
  console.error(err);
});

Any time you see this error ("// Unhandled 'error' event"), it means you need to find out what is emitting an error event and add a listener to handle the error.

Upvotes: 4

Related Questions