-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Return explicit error when trying to stream a non-Readable stream #2382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
lib/response.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just check for instance of Readable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately not. We need to rely on duck typing to support the common case of Readable streams created through the readable-stream module, which are not an instance of require('stream').Readable.
|
Will this work with the request module? |
|
This will error if |
|
But |
|
No, You have to Update: This is not a breaking change (unless you count the 8.1.0+ acceptance of |
|
Well, |
|
Sure, I don't mind – I just thought that you had a specific reason for the "streams2" compatible requirement mentioned in the API docs. This requirement breaks Do you still want to throw explicit errors for objectMode streams? If this check is disabled, objectMode streams will currently hang the client, and report an internal error like this: What about Writable only streams2 streams like those returned from |
|
I'd like a solution that keeps request working while giving the user some error about other invalid streams. |
|
By "keeps it working", I assume you mean "makes it work again"? An option for this, is to detect non-streams2 streams, and convert them to streams2 using wrap(). Maybe adding the The advantage of this approach is that all streams are streams2 internally, while allowing legacy streams to be used. On the flip side, it will add some bloat only to save people from wrapping the legacy streams themselves, calling Let me know which approach you think is more suitable, and I will try to update the patch. |
|
I don't want to do anything to the stream. Basically, try to figure out if it is a readable stream (1 or 2) and if it is not stream2 in object mode. Anything else just gets passed along. |
|
I think I understand what you want. This requires a review of all the internal stream processing to ensure it doesn't rely on the streams2 interface. At least the "close" handling has this dependency. |
|
It doesn't. It just calls |
83b9c9a to
351ad41
Compare
|
Ok, I spent quite a bit of time adding test cases for classic streams, which has led me to the conclusion that Hapi will have a hard time supporting classic streams on the current architecture, given that async processing takes place between I think the most sensible approach is to use the |
|
Passing along the status code from request was an actual feature added to hapi a long time ago. What's the status of this PR at this point? |
|
Is this feature actually tested in a meaningful manner? Are you referring to the The PR is mostly complete. One iffy part is this The other iffy part is that it breaks the api when rewriting the source. Maybe we should just create a new internal variable to hold this stream? This would also make the |
|
Ok, this turned out better than I thought it would. I managed to reuse the existing The only outstanding issue is the missing |
|
There is already logic to forward the status and headers. It just looks for a |
|
I know. I think I prefer that over the non-configurable The only issue with the Hapi code (as it is right now), is that it requires the values to be resolved before the processing is started. Eg. for var ready = function(res) {
this.removeEventListener('response', ready);
this.removeEventListener('error', ready);
reply(res);
};
Request.get('http://google.com').on('response', ready).on('error', ready);Incidentally, this code also works on the current Hapi release since it forwards the response stream. |
|
We are not trying to make it easier to use request, just to make sure we support the stream returned by request when used properly via the event or callback. |
|
I found another pitfall. If you use the base request object, Hapi will include the any request headers in the response, instead of the response headers. Hapi is probably a bit too eager to forward any header-like object it finds. |
|
Hmm, I believe this header forwarding behavior can be seen as a security issue. For instance a handler like: reply(Request.get('http://local.service/protected-data', { headers: { 'x-api-key': 'sekrit' } });will return the While this is the documented behavior ( |
|
I don't think it is. It is documented and has been this way for a long time. There is a flag to turn it off. Also, the example you give it a bug, no? You should not reply with the return request stream. |
|
I think you are going down a rat hole with this. The issue we need to fix is pretty limited. |
|
Ok, it seems there is some confusion on how
Hapi already supports 2 & 3. It seems that you are not aware of 1, which is the only case I'm trying to fix in this patch. The first variant of this patch just ensured a proper error was returned for case 1. The new revision instead tries to support this and any other classic stream. |
|
If I just remove the assert for object mode and not call wrap on the first option, what will happen? |
|
Then you will allow classic streams. While this will work under some circumstances, it can lose some of the initial stream data under others. This is what most of my new code deals with. |
|
I don't want to deal with it. People should stop using the request module. It's crap until they clean it up and make it work correctly with modern node (as in last 2 years). I rather put a note in the docs that you need to call |
|
Great, I guess we are back to my initial patch? Good thing I kept it around then ;-) |
0037838 to
33f4d6d
Compare
|
The patch is back to the initial conservative approach of erroring on non-compatible streams (including request type 1 streams). I have incorporated some of the extra tests i developed for the classic streams support into this patch as well. Please note that the new transmit.js test exposes an internal hapi error (see https://travis-ci.org/hapijs/hapi/jobs/51567581). This is not a bug introduced with this patch, as the same test will error on the existing codebase. |
This replaces "TypeError: Cannot read property 'objectMode' of undefined" error response Fixes hapijs#2368 & hapijs#2301
33f4d6d to
289337d
Compare
Return explicit error when trying to stream a non-Readable stream
|
This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions. |
Fix #2368 & #2301 by returning an explicit error for non
Readablestreams instead of throwing.This also fixes buggy behavior introduced in #2302, where a
Writableonly stream can be accepted as long as it contains asocket._readableStateobject.