-
Notifications
You must be signed in to change notification settings - Fork 7.3k
stream: Don't emit 'end' unless read() called #4969
Conversation
I'm worried about calling 'end' listener on already ended streams... Is it really needed? Can't we just handle this in |
the issue is that you can do stuff like this: server.listen(function(q, s){
sessionCheckDb(q, function(er, ok) {
if (ok) {
q.on('data', blah);
q.on('end', endIt);
} else {
s.end('please log in');
}
})
}) So, even without pipe(), it still can be an issue. |
This solves the problem of calling `readable.pipe(writable)` after the readable stream has already emitted 'end', as often is the case when writing simple HTTP proxies. The spirit of streams2 is that things will work properly, even if you don't set them up right away on the first tick. This approach breaks down, however, because pipe()ing from an ended readable will just do nothing. No more data will ever arrive, and the writable will hang open forever never being ended. However, that does not solve the case of adding a `on('end')` listener after the stream has received the EOF chunk, if it was the first chunk received (and thus, length was 0, and 'end' got emitted). So, with this, we defer the 'end' event emission until the read() function is called. Also, in pipe(), if the source has emitted 'end' already, we call the cleanup/onend function on nextTick. Piping from an already-ended stream is thus the same as piping from a stream that is in the process of ending. Updates many tests that were relying on 'end' coming immediately, even though they never read() from the req. Fix nodejs#4942
This commit breaks my code :( so I tried
which is the commit right before this one. And the broken code has disappeared. So I believe not sending "end" seriously breaking existing codes |
It might break your code, but generally if your code broke because of it - you were using API in a wrong way. Can you please post part of your code or reduced test case to demonstrate your problem? |
@indutny |
@inspiredjw What does "break" mean? What is happening? The two things that might be affected by this are:
In https://github.com/LearnBoost/knox/blob/master/lib/client.js, I see that you are listening for an There is another place which is harder to figure out, and I think is probably the issue: function registerReqListeners(req, fn){
req.on('response', function(res){ fn(null, res); });
req.on('error', fn);
} Here, you're listening to the An actual failing test would be great here. |
https://github.com/LearnBoost/knox
Knox's tests fail Automattic/knox#146 (comment) |
This solves the problem of calling
readable.pipe(writable)
after thereadable stream has already emitted 'end', as often is the case when
writing simple HTTP proxies.
The spirit of streams2 is that things will work properly, even if you
don't set them up right away on the first tick.
This approach breaks down, however, because pipe()ing from an ended
readable will just do nothing. No more data will ever arrive, and the
writable will hang open forever never being ended.
However, that does not solve the case of adding a
on('end')
listenerafter the stream has received the EOF chunk, if it was the first chunk
received (and thus, length was 0, and 'end' got emitted). So, with
this, we defer the 'end' event emission until the read() function is
called.
Also, in pipe(), if the source has emitted 'end' already, we call the
cleanup/onend function on nextTick. Piping from an already-ended stream
is thus the same as piping from a stream that is in the process of
ending.
Updates many tests that were relying on 'end' coming immediately, even
though they never read() from the req.
Fix #4942