Repository: koajs/koa
Pull request #923 (2017-02-28 07:44:10)

feat: set err.headerSent before app error event emit #919
cherry-pick from https://github.com/koajs/koa/pull/919

codecov[bot]: # [Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=h1) Report
> Merging [#923](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=desc) into [v1.x](https://codecov.io/gh/koajs/koa/commit/188feafdf089244dfaf4a22812c6394e01940b09?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.


```diff
@@         Coverage Diff         @@
##           v1.x   #923   +/-   ##
===================================
  Coverage   100%   100%           
===================================
  Files         4      4           
  Lines       424    426    +2     
  Branches    104    105    +1     
===================================
+ Hits        424    426    +2
```


| [Impacted Files](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [lib/context.js](https://codecov.io/gh/koajs/koa/compare/188feafdf089244dfaf4a22812c6394e01940b09...cb6350df80871c86099181e412e4a7072cba4755?src=pr&el=tree#diff-bGliL2NvbnRleHQuanM=) | `100% <100%> (ø)` | :white_check_mark: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=footer). Last update [188feaf...3be61e3](https://codecov.io/gh/koajs/koa/compare/188feafdf089244dfaf4a22812c6394e01940b09...3be61e36d1f13c180115bef7889009926fa29eed?el=footer&src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
codecov[bot]: # [Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=h1) Report
> Merging [#923](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=desc) into [v1.x](https://codecov.io/gh/koajs/koa/commit/188feafdf089244dfaf4a22812c6394e01940b09?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.


```diff
@@         Coverage Diff         @@
##           v1.x   #923   +/-   ##
===================================
  Coverage   100%   100%           
===================================
  Files         4      4           
  Lines       424    426    +2     
  Branches    104    105    +1     
===================================
+ Hits        424    426    +2
```


| [Impacted Files](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [lib/context.js](https://codecov.io/gh/koajs/koa/compare/188feafdf089244dfaf4a22812c6394e01940b09...cb6350df80871c86099181e412e4a7072cba4755?src=pr&el=tree#diff-bGliL2NvbnRleHQuanM=) | `100% <100%> (ø)` | :white_check_mark: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/koajs/koa/pull/923?src=pr&el=footer). Last update [188feaf...3be61e3](https://codecov.io/gh/koajs/koa/compare/188feafdf089244dfaf4a22812c6394e01940b09...3be61e36d1f13c180115bef7889009926fa29eed?src=pr&el=footer&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
jonathanong: no idea why codecov isn't working here

Patch:
diff --git a/lib/context.js b/lib/context.js
index 058b6a7..fb98ebc 100644
--- a/lib/context.js
+++ b/lib/context.js
@@ -104,14 +104,18 @@ var proto = module.exports = {
 
     if (!(err instanceof Error)) err = new Error('non-error thrown: ' + err);
 
+    var 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;
     }
 


Test patch:
diff --git a/test/context/onerror.js b/test/context/onerror.js
index fd5defd..94f0bc1 100644
--- a/test/context/onerror.js
+++ b/test/context/onerror.js
@@ -88,6 +88,29 @@ describe('ctx.onerror(err)', function(){
     })
   })
 
+  it('should ignore error after headerSent', function(done){
+    var app = koa();
+
+    app.on('error', function(err){
+      err.message.should.equal('mock error');
+      err.headerSent.should.equal(true);
+      done();
+    });
+
+    app.use(function*() {
+      this.status = 200;
+      this.set('X-Foo', 'Bar');
+      this.res.flushHeaders();
+      yield Promise.reject(new Error('mock error'));
+      this.body = 'response';
+    });
+
+    request(app.listen())
+    .get('/')
+    .expect('X-Foo', 'Bar')
+    .expect(200, function() {});
+  })
+
   describe('when invalid err.status', function(){
     describe('not number', function(){
       it('should respond 500', function(done){