Skip to content


Handle socket errors, add onConnectionError opt. #27

wants to merge 1 commit into from

3 participants


When not handling errors on the socket connection, long-lived requests (for example WebSocket connections) which eventually have a TCP timeout (for example, if the client has its network cable disconnected) will eventually cause an unhandled socket error which kills bouncy.

This change handles those errors. It also allows setting an option onConnectionError so that the code invoking bouncy can print a message when a connection error occurs. In order to do this, I stick the callback into opts and pass opts to the handler, which as a side-effect lets you pass the callback as an option, which I think is cleaner.

If you hate this approach, I can revert the opts.onConnectionError part of this change. Installing an error handler on the socket is pretty critical, though - otherwise we were seeing frequent bouncer death when using websockets.


I'm seeing similar issues with putting bouncy in front of projects where the bouncy instance dies.

  1. Passing onConnectionError is a bad interface. Use event emitters instead.

  2. What does this solve that you can't already do with bouncy(...).on('error', fn)? bouncy() just returns the net.Server object directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 12, 2012
  1. @sethml
Showing with 24 additions and 11 deletions.
  1. +6 −1 README.markdown
  2. +18 −10 index.js
7 README.markdown
@@ -64,7 +64,12 @@ bouncy(opts={}, cb)
If you specify `opts.key` and `opts.cert`, the connection will be set to secure
mode using tls. Do this if you want to make an https router.
-Your callback `cb` will get these arguments:
+You can specify a handler `opts.onConnectionError` which will be called
+when a connection from a client has an error. Your handler will be passed
+the error and the socket to the client.
+You may specify your callback either as an argument, or as `opts.callback`.
+Your callback will get these arguments:
28 index.js
@@ -11,20 +11,28 @@ var net = require('net');
var tls = require('tls');
var bouncy = module.exports = function (opts, cb) {
- if (typeof opts === 'function') {
- cb = opts;
- opts = {};
- }
+ if (typeof opts === 'function')
+ opts = { callback: opts };
+ opts = opts || {};
+ if (typeof cb === 'function')
+ opts.callback = cb;
- if (opts && opts.key && opts.cert) {
- return tls.createServer(opts, handler.bind(null, cb));
+ if (opts.key && opts.cert) {
+ return tls.createServer(opts, handler.bind(null, opts));
else {
- return net.createServer(handler.bind(null, cb));
+ return net.createServer(handler.bind(null, opts));
-var handler = bouncy.handler = function (cb, c) {
+var handler = bouncy.handler = function (opts, c) {
+ // If we don't handle socket errors, the server will die when a
+ // connection times out.
+ c.on('error', function (err) {
+ if (opts.onConnectionError)
+ opts.onConnectionError(err, c);
+ });
var parser = parsley(c, function (req) {
@@ -52,14 +60,14 @@ var handler = bouncy.handler = function (cb, c) {
// don't kill the server on subsequent request errors
req.on('error', function () {});
var bounce = makeBounce(stream, c, req, parser);
- cb(req, bounce);
+ opts.callback(req, bounce);
req.on('headers', onHeaders);
function onError (err) {
req.removeListener('headers', onHeaders);
var bounce = makeBounce(stream, c, req, parser);
- cb(req, bounce);
+ opts.callback(req, bounce);
req.emit('error', err);
req.once('error', onError);
Something went wrong with that request. Please try again.