Welcome to the Linux Foundation Forum!

Suggestion about error handler in express

I have this idea when I am at Streaming Content with Express (2).

As the tutorial states, error handler of express always respond with HTML describing the error the server has.

If we change the Content-Type to something except text/html, for example, application/json, then browser will receive a HTML response while the header of which is not application/json. Browser will be confused due to header and content mismatch.

According to the last step of Streaming Content with Express (2), when I navigate to http://localhost:3000/articles?type=json, the response looks like this in the browser:

Maybe we can reset the response type in the error handler to inform the clients of the correct Content-Type.

  // render the error page
  res.type('text/html')
  res.status(err.status || 500);
  res.render('error');

Comments

  • krave
    krave Posts: 58

    Another observation about express is streaming error handling.
    Say pipe some stream to res.

    someStream.pipe(res)
    

    And something goes wrong during the process before end event of the stream emitted.

    someStream.destroy()
    

    Before someStream.destroy() being invoked, HTTP headers have already been sent to the client.
    If I propagate Error [ERR_STREAM_PREMATURE_CLOSE] to next() function of the route handler, express will also invoke res.render('error'); in app.js to respond to the HTTP request. Then express will complain that

    Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

    So I would like to know what is the appropriate way to handle error when piping stream to HTTP response. The default behavior of express doesn't seem to be the best solution.

  • xdxmxc
    xdxmxc Posts: 110

    @krave

    const { finished } = require('stream')
    // handler setup etc etc
    handler.get('/foo/bar', (req, res, next) => {
       const stream = createStream(req.data.whatever)
       finished(stream, (err) => {
         if (err) return next(err)
         res.end('finished')
         next()
       })
    })
    

    Streams can close for various reasons, using the finished function covers all the cases.

    If you're looking to pipe you can use stream.pipeline to combine the best of both .pipe and finished:

    const { pipeline } = require('stream')
    // handler setup etc etc
    handler.get('/foo/bar', (req, res, next) => {
       const stream = createStream(req.data.whatever)
       pipeline(req, stream, res, next)
    })
    

Categories

Upcoming Training