Way to set headers on HttpErrors
See original GitHub issueCurrently, the default error handler in koa checks for the status property on errors and sets the status accordingly. However, many errors in the HTTP spec are defined with required or recommended headers to be send along with the status. For example, 405 Method Not Allowed should always be sent with an Allow header, a 503 Service Unavailable with a Retry After.
Currently, it is not possible to set this. You could write your own error handler that checks a headers
property on the error object, but third party middleware can’t rely on that. As a result, middleware modules on npm (like koa-router etc.) have to set status and headers on the context response manually instead of throwing an error, which means it is not possible to catch them and therefor destroys one of the best features of koa - error handling with try / catch.
It would be nice if the koa error handler would check for the existence of a headers
property on the object and set the headers in that hash (with normalized casing). http-errors already supports passing a properties hash in the constructor, so it could look like this:
throw new HttpError(405, {headers: {'Allow': 'GET, POST'}})
throw new HttpError(503, {headers: {'Retry-After': 60}})
This would then allow middlewares from npm to actually throw errors that can be catched to add some additional custom text etc. Thoughts?
Issue Analytics
- State:
- Created 8 years ago
- Comments:30 (30 by maintainers)
Top GitHub Comments
why just ‘don’t remove’ the headers already set ? because with this solution when you want keep a header set by module X from module Y you have to reference errors set in modules X in modules Y? or maybe a flag to say i want remove all header on error, and not i want keep some headers?
it is a bad thing if the middleware automatically responds with 401 if I always wanted to respond with an uniform JSON error response in my API (Google APIs do this, for example). This is especially true if you have the requirement to follow HATEOS, so you always need to provide links in the response body. Just an example. Then it would be nice to do this:
this is all pseudocode of course. The point is, it doesn’t work, because jwtMiddleware responds directly with 401 - because if it throws, it can’t add additional info aka headers. Sure jwt could implement a
errorResponseTransformer
option or something like that, but at that point we would be basically passing middleware functions to factories, wtf xDIn your example, middleware could technically modify
Retry-After
, but the only function that knows what value makes sense is the middleware that threw the 503. 503 might be a bad example, but equally only the authorization middleware knows thatWWW-Authenticate
should beBasic
orDigest
, only the router knows that thatAllow
needs to beGET, PUT
.In the end, there are no exceptions in javascript, only errors. And one of the great things about javascript is that we can attach custom stuff to objects. Do I understand you correctly that you think thrown errors should only be for stuff that seriously went wrong and have nothing to do with HTTP, so basically only 500? We should remove http-errors then 😉
But I get your thoughts… somewhere we need to draw the line. Next we allow a
body
property on the error… And koa3 middleware functions get only passed the request and either call next,return new KoaResponse({status, body, headers})
orthrow new KoaErrorResponse({status, body, headers})
… It’s just where should this line be drawn? 1) Keep errors out of HTTP responses? 2) Allow status and message (current behaviour)? 3) allow headers too? Imo either 1 or 3.