diff --git a/lib/application.js b/lib/application.js index 379943f..3ba9193 100644 --- a/lib/application.js +++ b/lib/application.js @@ -97,7 +97,9 @@ app.callback = function(){ return function(req, res, next){ var ctx = self.createContext(req, res); - co.call(ctx, gen)(next || ctx.onerror); + next = next || ctx.onerror; + ctx.socket.once('error', next); + co.call(ctx, gen)(next); } }; diff --git a/lib/context.js b/lib/context.js index 584f0e8..bfade5b 100644 --- a/lib/context.js +++ b/lib/context.js @@ -94,7 +94,7 @@ module.exports = { // nothing we can do here other // than delegate to the app-level // handler and log. - if (this.headerSent) { + if (this.headerSent || !this.socket.writable) { err.headerSent = true; this.app.emit('error', err, this); return; diff --git a/test/application.js b/test/application.js index 1fbb76c..64f7c8d 100644 --- a/test/application.js +++ b/test/application.js @@ -5,6 +5,26 @@ var http = require('http'); var koa = require('..'); var fs = require('fs'); +describe('app', function(){ + it('should handle socket errors', function(done){ + var app = koa(); + + app.use(function *(next){ + // triggers this.socket.writable == false + this.socket.emit('error', new Error('boom')); + }); + + app.on('error', function(err){ + err.message.should.equal('boom'); + done(); + }); + + request(app.listen()) + .get('/') + .end(function(){}); + }) +}) + describe('app.use(fn)', function(){ it('should compose middleware', function(done){ var app = koa();