Brad Brad - 5 months ago 19
Node.js Question

Proper Node.js API for determining whether or not `100 Continue` was sent

I have a strange edge case of HTTP and HTTP-like handling where I have to support some broken clients. Specifically, a client will make an HTTP PUT request, and I need to send a

200 OK
after the request headers are received, before the client sends its request body. Normally, I do this:

app.put('/*', function (req, res, next) {
res.socket.write('HTTP/1.0 200 OK\r\n\r\n');
/* Pipe socket and handle data here */
}


However, with newer versions of Node.js (v6.2.2 as of this writing), when a client connects with a proper HTTP/1.1 request and
Expect: 100-continue
in its request headers, the HTTP server will (correctly) send an
HTTP/1.1 100 Continue
message, immediately before I get a chance to send my own response status line. As a result, the client would get two status lines:

HTTP/1.1 100 Continue
HTTP/1.0 200 OK


This isn't a huge problem. I just need to detect when the Node.js HTTP server took care of the status line, so I don't send a duplicate. The trick is, I don't think this API is properly exposed. I prodded around and came up with this method:

app.put('/*', function (req, res, next) {
if (!res._sent100) {
res.socket.write('HTTP/1.0 200 OK\r\n\r\n');
}
/* Pipe socket and handle data here */
}


My Question: Is there a better way to detect when the built-in HTTP server has sent
100 Continue
than by using
res._sent100
?

There is an HTTP server
checkContinue
event
. However, if I handle that event then the normal events don't fire. I'm using this in conjunction with Express, and I need the normal request events so that the normal middleware stack will run. If I could handle
checkContinue
, write my own property to
res
, and then pass it back to the normal stack for handling, then all would be well. But, I don't see a documented way to do this.

Answer

This seems to work:

server.on('checkContinue', (req, res) => {
  res.mySent100 = true;
  res.writeContinue();
  server.emit('request', req, res);
});

(where server is the HTTPServer instance that is serving your Express app)