question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Way to set headers on HttpErrors

See original GitHub issue

Currently, 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:closed
  • Created 8 years ago
  • Comments:30 (30 by maintainers)

github_iconTop GitHub Comments

2reactions
menemscommented, Jan 25, 2016

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?

1reaction
felixfbeckercommented, Nov 1, 2015

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:

app.use(async (ctx, next) => {
  try {  
    next();
  } catch (err) {
    ctx.response.body = {
      error: err.message,
      code: err.code
    };
    if (err.status === 401) {
      ctx.response.body.link = '/token';
    }
    throw err;
  } finally {
    switch (ctx.accepts('json', 'xml')) {
      case 'json': ctx.response.body = JSON.stringify(ctx.response.body); break;
      case 'xml': ctx.response.body = XML.stringify(ctx.response.body); break;
    }
  }
})
app.use(errorLogger());
app.use(jwtMiddlware({secret: 'suchsecretverywow', issuer: 'doge'});

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 xD

In 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 that WWW-Authenticate should be Basic or Digest, only the router knows that that Allow needs to be GET, 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}) or throw 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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handle HttpError with custom headers in React Admin
I'm using custom headers as specified here: const httpClient = (url, options = {}) => { if (!options.headers) { options.headers = new ...
Read more >
HTTP Errors <httpErrors> - Microsoft Learn
How to add a custom error page · Hold down the Windows key, press the letter X, and then click Control Panel. ·...
Read more >
http headers vanish when proxying http errors through nginx
I'm using add_header X-Content-Type-Options nosniff; in nginx to add this header to every response. If the HTTP status code returned by Apache ...
Read more >
Serve Dynamic Custom Error Pages with HAProxy
This blog post covers how to set up custom error pages in HAProxy in order to ... dynamic error handling with the new...
Read more >
Handling Errors in Express | Zell Liew
How to handle Express errors. ... npm install http-errors --save ... Don't panic if you see an error that says “Cannot set headers...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found