Description
- Version: v10.13.0
- Platform: Windows 10
- Subsystem: http
I noticed a different in how the HTTP/1 request objects are left after a HTTP/1 framing error (which causes an error in the underlying http_parser). In Node.js 8 and below, the request object would be destroyed and be left in non-readable state (i.e. req.readable === false
). It seems like in Node.js 10+ this is no longer the case. Is this an expected change? Express.js has underlying machinery that is looking to see if a request body should be read (since the request starts out in a pasued state since 0.10) and it doesn't attempt to read when it's no longer readable (since events like 'end'
will not be emitted, leaving things hanging around forever).
Here is an example that reproduces the scenario:
var http = require('http')
var net = require('net')
var server = http.createServer(function (req, res) {
setTimeout(function () {
if (!req.socket.readable) {
console.log('req already terminated')
server.close()
return
}
console.log('req read start')
var bufs = []
req.on('data', function (chunk) {
console.log('request recv %d bytes', chunk.length)
bufs.push(chunk)
})
req.on('end', function () {
var data = Buffer.concat(bufs)
console.log('request got %d bytes', data.length)
res.end('OK')
})
req.on('close', function () {
console.log('clean up here...')
server.close()
})
}, 5000)
})
server.listen(0, function () {
var port = server.address().port
var sock = net.createConnection(port, '127.0.0.1')
sock.on('connect', function () {
sock.write('POST / HTTP/1.1\r\n')
sock.write('Host: localhost\r\n')
sock.write('Transfer-Encoding: chunked\r\n')
sock.write('\r\n')
sock.write('W')
sock.on('close', function () {
console.log('client socket closed')
})
})
})
setTimeout(function () {
console.log('timeout!')
process.exit(1)
}, 10000).unref()
In Node.js 8 and lower you get the following output:
client socket closed
req already terminated
In Node.js 10 you get the following output:
req read start
timeout!
I'm not sure if this was an expected change or not. If it is an expected change, I'm just looking for what the correct way to know if a bit of code (the part inside setTimeout
) that runs at an arbitrary time after the request came in should know if it's actually ever going to get a complete read or not. The only thing I've found so far in Node.js 10 is that you have to try and read no matter what and just rely on coding in a read timeout to know when to give up instead of knowing earlier.