From e452b68bd9eecad2f517bf4e8fddadea0bca3d19 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Tue, 28 Feb 2017 10:52:54 +0800 Subject: [PATCH] feat: set err.headerSent before app error event emit (#919) --- lib/context.js | 8 ++++++-- test/context/onerror.js | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/context.js b/lib/context.js index 93be63f..94b5a42 100644 --- a/lib/context.js +++ b/lib/context.js @@ -106,14 +106,18 @@ const proto = module.exports = { if (!(err instanceof Error)) err = new Error(`non-error thrown: ${err}`); + let headerSent = false; + if (this.headerSent || !this.writable) { + headerSent = err.headerSent = true; + } + // delegate this.app.emit('error', err, this); // nothing we can do here other // than delegate to the app-level // handler and log. - if (this.headerSent || !this.writable) { - err.headerSent = true; + if (headerSent) { return; } diff --git a/test/context/onerror.js b/test/context/onerror.js index 322c185..61b989d 100644 --- a/test/context/onerror.js +++ b/test/context/onerror.js @@ -86,6 +86,29 @@ describe('ctx.onerror(err)', () => { }); }); + it('should ignore error after headerSent', done => { + const app = new Koa(); + + app.on('error', err => { + err.message.should.equal('mock error'); + err.headerSent.should.equal(true); + done(); + }); + + app.use(async ctx => { + ctx.status = 200; + ctx.set('X-Foo', 'Bar'); + ctx.flushHeaders(); + await Promise.reject(new Error('mock error')); + ctx.body = 'response'; + }); + + request(app.listen()) + .get('/') + .expect('X-Foo', 'Bar') + .expect(200, () => {}); + }); + describe('when invalid err.status', () => { describe('not number', () => { it('should respond 500', done => {