-
-
Notifications
You must be signed in to change notification settings - Fork 20.9k
Description
Recently I have found my self in two different situations where I needed to abort a response that I already started streaming. Doing this in a reliable way across different situations proved to be quite hard. We finally came up with a solution to the problem.
function abortStreamingResponse(res) {
/* If you encounter an error after initializing a streaming response,
* it is not straight forward to abort it and cause the response to
* be interpreted as an error in the browser.
*
* This was the only reliable way we found to interrupt the streaming
* response in all cases.
*
* There's two cases that you have to consider when doing this:
*
* 1: You encounter an error before the headers are sent.
* 2: You encounter an error after the headers are sent.
*
* Express will claim that the headers are sent (res.headersSent), even
* before they are actually written to the socket. By writing something
* that looks like a valid response header in addition to what Express
* has already written, or has qued to be written, you will cause the
* response to inevitable cause an invalid chunked encoding error.
*/
res.connection.write(
'HTTP/1.1 500 Let\'s ruin that response!\r\n' +
'Content-Type: text/plain\r\n' +
'Transfer-Encoding: chunked\r\n\r\n'
);
res.end();
}
We had multiple places across our application where we could encounter errors in the source streams that we pipe to res, so we actually went even further. We added an error handler, that incorporated this method.
return function (err, req, res, next) {
var responseObj = { ... };
// If res.headersSent is true, Express has either written
// the response headers to the socket, or qued them to be
// written. Which means that we will get an exception if
// we try to set the status code of the response etc. When
// we need to handle an error after that moment we need to
// corrupt the response already given to the client.
if (res.headersSent) {
return abortStreamingResponse(res);
}
return res.status(statusCode).send(responseObj);
}
This allows us to pass errors to the next callback, even after we started writing the response. The result in the browser will be an error ERR_INVALID_CHUNKED_ENCODING
in Chrome, and similar errors in other browsers.
What have you done when you have been in similar situations?
It seems like a problem that you would run into constantly when developing applications where you are streaming stuff out to clients over HTTP. But I have not been able to find any mentions about it when searching around. It seems like something you'd want to have a baked in solution to in Express - I'm not saying that it should be my solution - but just some solution.