-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
HTTP Client 'aborted' event fires even when request was ok #18756
Comments
I can't reproduce what you're seeing, the file is the expected size and
Is that a typo? Anything < v4.x is obsolete. |
Yes, that's a typo. Fixed now. Sorry. If you leave the script running for a bit you should see some of the requests with aborted = true. here is my output running on Ubuntu/x64 with node v8.9.4:
|
@billywhizz Chances are that we haven't received the final /cc @nodejs/http @nodejs/http2 |
It would have to be something else, because the code in the gist is printing out the I see this in the RFC:
But it seems like it's not closed before the last octet is received, since it's there in the download, it would seem. I haven't debugged through it yet, but it would seem that if the connection is aborted just after that last octet is received, it shouldn't emit aborted on the actual response object, since the response wasn't aborted (the connection was aborted after the response finished cleanly). |
@dougwilson it seems you're right, if we receive a message body with a matching Content-Length then we shouldn't be emitting I haven't even tried the sample script so not sure if I can reproduce. Might have time to look into it this coming weekend if no one else does. |
for context, here are the tests we were trying to get passing. if we don't handle the 'aborted' event we occasionally get a completed download with no errors but the file size is truncated. if we handle the 'aborted' event and don't check for res.complete then more often we get good downloads being reported as aborted.
if we change to not check the res.complete here we will get occasional errors in final two tests as in the earlier gist i posted. |
This diff on node release v8.9.4 fixes the issue for my tests so i can just handle 'aborted' and it works as expected. -diff --git a/lib/_http_client.js b/lib/_http_client.js
index fa9e4e2..a1d2580 100644
--- a/lib/_http_client.js
+++ b/lib/_http_client.js
@@ -350,7 +350,7 @@ function socketCloseListener() {
req.emit('close');
if (req.res && req.res.readable) {
// Socket closed before we emitted 'end' below.
- req.res.emit('aborted');
+ if (!req.res.complete) req.res.emit('aborted');
var res = req.res;
res.on('end', function() {
res.emit('close');
a |
@billywhizz that was good research! Would you mind sending out a PR with a fix? |
@mcollina sure thing. i should have one for you in morning. will read up on the guidelines first. i can likely also add some tests based on the ones i posted above. |
yes definitely! @dougwilson what do you think of that proposed fix? |
Trying it out with a test server, the behavior change with the patch looks like what I would expect 👍 |
i spent some time last night and was not able to reproduce the error using tests i wrote according to the ones that are currently there in nodejs repo. i am wondering if it's some weird edge case being caused by my other tests. will do some more digging and report back if i find anything useful. |
I can now make the error happen in a test but using the external site to serve the file and only happens intermittently. i captured a debug trace to compare sequence of events when it fails and when it doesn't and you can see it here. hopefully will be able to produce a test that triggers that condition reliably. |
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756
I'm working on this branch for a PR: https://github.com/billywhizz/node/commits/fix-http-client-aborted. After a lot of investigation and testing i am pretty confident the fix is good. I am not able to get an automated test that reliably reproduces the error as it seems to depend on how the server handles closing the TCP session. It might be possible to mock it if i can figure out exact sequence of events to make it happen. Any suggestions welcome. If you want to make the error happen you can remove my commit and run this command and it should happen intermittently:
I haven't been able to make the error happen as yet on that test url when using my commit. |
I would recommend using the debugger to figure out the exact sequence of things that should happen, and approximate it at best. Worst case, set completed to true yourself and call the method. We won’t accept a PR relying on an external service to run a test. Feel free to send a PR with what you have, and we can iterate from there. |
I'll give it a go matteo. I think I have narrowed it down to the fact that when the error happens the socket close callback seems to fire pretty much immediately (maybe because server has already closed their end?). this means the HTTP socket close function gets called before the stream is ended and cleaned up. that is why we see the "aborted" code being hit with the stream still in a readable state and is where my fix runs to check the incomingmessage is complete or not. I am not sure if that is a bigger bug in how the closing of the socket is handled or not. here are some debug logs which show the difference between a successful one:
and the one that fails:
|
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. Fixes: nodejs#18756
@mcollina let me know what you think about this. maybe there is a better way to do it but with this i can reliably recreate the condition and have verified it fails test before my change and passes after: billywhizz@d54f7ba |
let me know if you are happy for me to make the PR based on the above guys. |
Please fire a PR. It would be easier to review and gather feedback. |
Pull Request created here: #18999 |
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Tests in progress to reproduce issue consistently. Fixes: nodejs#18756 PR-URL: nodejs#18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
When socket is closed on a response for a request that is being piped to a stream there is a condition where aborted event will be fired to http client when socket is closing and the incomingMessage stream is still set to readable. We need a check for request being complete and to only raise the 'aborted' event on the http client if we have not yet completed reading the response from the server. Fixes: #18756 Backport-PR-URL: #22380 PR-URL: #18999 Reviewed-By: Shingo Inoue <leko.noor@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
We have been having issues with http/https downloads failing silently and the file being downloaded having an incorrect size for some time now. We are using axios library to do download and after some research and testing the only way we could get alerted about an incomplete download (connection is forcibly closed by server in middle of downloading body) was to handle the http response "aborted" event.
However, when we handled this we noticed we were having good downloads, where file contents were completely received, reported as "aborted".
Maybe this is intended behaviour but it makes more sense to me to only receive aborted event on a client response if the socket close happened before the active http response has been received completely. Currently, there is no check for the current active response having completed or not before firing the aborted event.
You can see the behaviour in this gist - the firing of the aborted event seems completely random and is likely due to timing of when the server closes the socket.
Our workaround is to use the commented code here to check if the current response is complete and ignore the aborted event if so.
Should the same logic be used in node.js core? Appreciate this could cause issues for existing libraries depending on current behaviour.
The text was updated successfully, but these errors were encountered: