Merge pull request #678 from PlasmaPower/cherrypick-to-next
Add support for headers in errors (v2.x)
This commit is contained in:
commit
882ea7e87a
3 changed files with 80 additions and 1 deletions
44
docs/error-handling.md
Normal file
44
docs/error-handling.md
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Error Handling
|
||||
|
||||
## Try-Catch
|
||||
|
||||
Using generators means that you can try-catch `next`. For example,
|
||||
this example prepends all error messages with "Error: "
|
||||
|
||||
```js
|
||||
app.use(function*(next){
|
||||
try {
|
||||
yield next;
|
||||
} catch (error) {
|
||||
error.message = 'Error: ' + error.message;
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Default Error Handler
|
||||
|
||||
The default error handler is essentially a try-catch at
|
||||
the very beginning of the middleware chain. To use a
|
||||
different error handler, simply put another try-catch at
|
||||
the beginning of the middleware chain, and handle the error
|
||||
there. However, the default error handler is good enough for
|
||||
most use cases. It will use a status code of `err.status`,
|
||||
or by default 500. If `err.expose` is true, then `err.message`
|
||||
will be the reply. Otherwise, a message generated from the
|
||||
error code will be used (e.g. for the code 500 the message
|
||||
"Internal Server Error" will be used). All headers will be
|
||||
cleared from the request, but any headers in `err.headers`
|
||||
will then be set. You can use a try-catch, as specified
|
||||
above, to add a header to this list.
|
||||
|
||||
## The Error Event
|
||||
|
||||
Error handlers can be specified with `app.on('error')`.
|
||||
If no error handler is specified, a default error handler
|
||||
is used. Error handlers recieve all errors that make their
|
||||
way back through the middleware chain, if an error is caught
|
||||
and not thrown again, it will not be handled by the error
|
||||
handler. If not error event handler is specified, then
|
||||
`app.onerror` will be used, which simply log the error if
|
||||
`error.expose` is true and `app.silent` is false.
|
|
@ -117,8 +117,9 @@ const proto = module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
// unset all headers
|
||||
// unset all headers, and set those specified
|
||||
this.res._headers = {};
|
||||
this.set(err.headers);
|
||||
|
||||
// force text/plain
|
||||
this.type = 'text';
|
||||
|
|
|
@ -52,6 +52,40 @@ describe('ctx.onerror(err)', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should set headers specified in the error', done => {
|
||||
const app = new Koa();
|
||||
|
||||
app.use((ctx, next) => {
|
||||
ctx.set('Vary', 'Accept-Encoding');
|
||||
ctx.set('X-CSRF-Token', 'asdf');
|
||||
ctx.body = 'response';
|
||||
|
||||
throw Object.assign(new Error('boom'), {
|
||||
status: 418,
|
||||
expose: true,
|
||||
headers: {
|
||||
'X-New-Header': 'Value'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const server = app.listen();
|
||||
|
||||
request(server)
|
||||
.get('/')
|
||||
.expect(418)
|
||||
.expect('Content-Type', 'text/plain; charset=utf-8')
|
||||
.expect('X-New-Header', 'Value')
|
||||
.end((err, res) => {
|
||||
if (err) return done(err);
|
||||
|
||||
res.headers.should.not.have.property('vary');
|
||||
res.headers.should.not.have.property('x-csrf-token');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when invalid err.status', () => {
|
||||
describe('not number', () => {
|
||||
it('should respond 500', done => {
|
||||
|
|
Loading…
Reference in a new issue