-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
http: don't error after http client response #28668
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
|
@benjamingr ping |
b24c8f7 to
74add0b
Compare
|
The main question here is: "What should happen if writing to a request who's response has ended?" Should it return true/false? Should it emit an error? Even though emitting some form of error might seem the most semantically correct it makes the API very hard to use. I would prefer a noop + a dump ( |
8601f70 to
1915854
Compare
Users have no way to know they are doing something wrong if it fails silently. |
I would argue that they are not doing anything wrong... it's perfectly valid to end a response before receiving the whole request. |
|
Hm, maybe you are right. I'm having trouble wrapping my head around this one. |
|
In my opinion intentional or unintentional writing to |
1915854 to
44c3fef
Compare
|
@lpinca how about this version? |
|
Though |
8d883c8 to
57fd0b3
Compare
|
@lpinca: Question. Is it valid to write data to a request after having received a response and the response has not ended? I'm a bit unsure. If no, then this issue is easier to resolve. i.e. is something like this valid: server.on('request', (req, res) => req.pipe(res)) |
e165a88 to
f1ffdb6
Compare
|
@lpinca another try... |
I think it is invalid, it does not make much sense. |
|
Ok. That works for me. Should we have a new error? e.g. ‘WRITE_AFTER_RESPONSE’? |
|
All data is actually discarded Line 629 in 84ad92d
if the user is not consuming the data. |
Works for me. |
|
On the server, does it make sense to keep reading the request (if not complete) if you are already writing the response? I'm not sure, I think not. |
|
What does the spec say? |
This is after response has finished. |
|
The issue happens after response is finished (server-side) when socket is destroyed |
|
I’m confused. Is the PR fine as is? I.e. we error if the response is finished. Or when the response has started? |
|
I think it will not work if we wait for it to be finished because the write can occur before |
daa197d to
504e6b5
Compare
|
@lpinca updated according to our discussion |
504e6b5 to
c5f9627
Compare
|
Ok this is more or less what I had in mind with #27916 (comment). Btw we still have an error so I'm not sure if it is much better than original behavior. |
|
|
||
| ClientRequest.prototype.write = function write(chunk, encoding, callback) { | ||
| if (this.res) { | ||
| this.emit('error', new ERR_REQUEST_WRITE_AFTER_RESPONSE()); |
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.
This will allow the 'error' event to be emitted multiple times, are there other case where this can happen?
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.
The alternative would be worse though (throwing outside) no?
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.
If I'm not wrong the original ECONNRESET is forwarded to the ClientRequest instance.
|
Hmm, can we get implementor feedback from express/fastify? I am also more in favor of "this should error" but I am really bit sure. |
|
I'm more in favor of not error. Since that would be less "painful". This error is not harmful per se and will cause things that don't necessarily have to fail, to fail. But I'm fine with either as long as it is consistent and predictable. But I do require it requires some additional fixes such as #28672. It's a bit similar to the considerations in #20077. |
The changes as they are currently in the PR look like they only deal with the Node.js HTTP client (vs the Node.js HTTP server which would be express/fastify/etc.), is that right? I tried to read though and understand the conversation above as well, though. If looking for general HTTP/1 guidance, though, the HTTP sever is allowed to start writing the response before the client has completed writing the HTTP request to the wire; notably the 1xx series of response codes, where the client expects multiple HTTP responses to a single request. This can sometimes be taken advantage of by servers to provide upload progress to the clients; I have worked on software that took advantage of this by immediately sending back a HTTP 200 HTML response before a multipart request was completed with incomplete HTML, trickling down more HTML to update a progress bar for the user to see. The down side is that intermediaries between the end-user and the server can make it not work as intended. This specific technique has become obsolete with XHR 2's progress event tracking in JavaScript if using a FormData object to upload, these days, but just used it as a read-world example of a server sending back response data while the request data is still being sent, if there was a question on that in the conversation. RFC 723x series does not provide specific guidance around this that I know of, so it's open for servers and clients to interpret. I hope that information helps with this PR. |
|
Ok, then I think we should not move this patch forward. |
|
@lpinca how about doing check for whether the res has ended? i.e. if (this.res && this.res.closed) {
this.emit('error', new ERR_SOCKET_CLOSED());As you pointed out the problem occurs here: Line 615 in ac95c2f
And we could set Alternatively we could maybe do: if (this.res && !this.res.socket) { |
|
The problem as I see it is that you don't know the other peer destroyed the socket until you write to it. On the client |
mcollina
left a comment
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.
I prefer an implementation that did not overload write and end any further.
mcollina
left a comment
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.
I'm not in agreement in having this change landed at all. I think It's a perfectly valid case to start receiving a response before we have finished sending the request.
|
I think we are all in agreement about not landing this. I suggest we go back to #27916 and try to find an alternative approach. |
This tries to solve #27916. Where an
errorcan be emitted from aHttpClientrequest after the response has beenended.In particular see the comment #27916 (comment)
Depends on #28621.
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes