stream-utils / raw-body

Get and validate the raw body of a readable stream

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When the request connection is closed prematurely, the module never yields

peterjwest opened this issue · comments

I have been testing out the case where a request terminates before properly finishing. Using the following code to simluate this request:

var http = require('http');
var options = {
  host: 'localhost',
  path: '/'
};
var req = http.request(options, function(res) {
  res.on('data', function () {});
  res.on('end', function () {});
});

req.write('123');

setTimeout(function() {
  process.exit();
}, 200);

In this case the module never yields because only the close event triggers.

Hi! Can you post the server-side as well that I can point that script at to reproduce?

i guess we could create/pass an ECONNRESET error.

Ah, yes, I see we just do cleanup on close instead of doing anything else. I'll get a fixup ASAP!!

This test script should work:

var app = require('express')();
app.use(function(req, res, next) {
    req.on('data', function() {
        console.log('data');
    });
    req.on('error', function() {
        console.log('error');
    });
    req.on('close', function() {
        console.log('close');
    })
    req.on('end', function() {
        console.log('end');
    })
});
app.get('/', function(req, res) {
    res.end('test');
});
app.listen(3000);

You should see that when you use the client script on this you only get the close event, not the end event (client script will need the port adding).

The biggest issue in the fix is that streams in Node.js can legitimately close before they end, so just erroring on a close before end isn't good enough :(

Ok, so it should be fixed on the current master right now if you want to confirm, @peterjwest

Works great, thanks!

Just wondering how can a stream close before it ends?
And in what circumstances would the stream.once('error', onEnd) event trigger?

Awesome, @peterjwest , I'm going to publish in just a few minutes :)

Just wondering how can a stream close before it ends?

This is really a question to ask Node.js core developers, but the gist is that the close event is for the underlying resource and the end event is for your reading of the stream. In streams2+ each stream has an internal buffer with a high and low watermark. Node.js will read from your resource to fill at least up to the low watermark. Of course, if you are not actually reading from the stream and Node.js, while filling this buffer, completes reading from the underlying resource (like a file), it can emit the close event to close the file descriptor. You can still read the rest of the buffered data and get the end event, but the close event already fired.

And in what circumstances would the stream.once('error', onEnd) event trigger?

When an error is emitted on the stream. This would probably better explained by Node.js core as a general streams question, but in general any stream can emit an error (and if you don't have an error listener on the stream, your program will then crash).

I'm going to publish in just a few minutes :)

Actually, I'm going to delay the release of this until later tonight (US time) so I can evaluate the impact of releasing as a patch vs minor release. If you really need the fix before then (just like 12 hours at most), you can always npm install stream-utils/raw-body or add "raw-body": "stream-utils/raw-body#3996c21e" to your package.json :)

Thanks a lot for the answers, really helpful!

It totally makes sense that a stream can close before it ends, but given that I do wonder why the close event doesn't usually fire :/

Well, that doesn't apply to HTTP streams, but this library isn't actually limited to HTTP streams only.

Just published this as 1.3.4, by the way

Thanks again. <3 node community.