You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since node.js 6.8.0, http.request supports timeout option. (api-doc)
I test this feature with below code:
'use strict';varhttp=require('http');constserver=http.createServer((req,res)=>{console.log(Date.now(),'Server get incoming request');setTimeout(()=>{// delay 10 secondsconsole.log(Date.now(),'Server send response');res.writeHead(200,{'Content-Type': 'text/plain'});res.write('Hello');res.end();},10000);});server.listen(8000);constreq=http.get({hostname: '127.0.0.1',port: 8000,path: '/',timeout: 100// timeout in 0.1 second},function(response){// not expectedconsole.log(Date.now(),'Get response from server');process.exit();});req.on('error',(err)=>{console.log(Date.now(),'Error',err);process.exit();});
Output I got:
1490270444601 'Server get incoming request'
1490270454604 'Server send response'
1490270454608 'Get response from server'
The response was delayed 10 second to send and I expected a ETIMEOUT on http client. But it didn't.
What's more, I read the file change in #8101 which is PR adding timeout to http.request, the test case seems not testing http.request's timeout option.
@neroux As document says: it specifies the socket timeout. Socket timeouts after a duration of inactivity on the socket. It should cover both connect timeout and read timeout.
First, when you call socket.setTimeout() before a socket is connect, the idle timer is kept until the socket is destroyed or setTimeout(0) is called. A socket won't clear its idle timer when it gets connect.
The timeout parameter in option is passing through from http.request to http.Agent, then to net.createConnection and finally set on Socket. And I trace the connect event route and can't find any place that removes the timer.
@aleung yes, that confirms what @mcollina wrote.
If the socket stays in idle for more than timeout time a 'timeout' event will be emitted on the socket without closing (severing) the connection.
@lpinca Thanks for the explaination. However, I don't think I get an answer about whether my issue is valid or not.
My test case shows that 'timeout' event is not got on ClientRequest when I use http.request with timeout option. If I'm not using http but am using plain socket, 'timeout' event is triggered on read timeout. The behaviour of using timeout option in these two scenrioes are different.
Is it an issue on http module? Or it's intended? If it's intended, should the document of http.request be updated to state that the timeout is only for connection estiblishing but not for read?
Anyway, I believe when someone uses http.request and specfies timeout option, what he expects is to capture any timeout on the request till it ends rather then only connection estiblishing.
Documentation should be updated to reflect the actual behavior though.
Reacted by Ayoub Gdah, Dave T. Johnson, Loreto Parisi, Ján Dzurek, inoperable, S. Mahdi Mir-Ismaili, Dmitry Shabanov, Govind Rai and Behzad Khosravifar
@manoharreddyporeddy in that example I see req.destroy(); on timeout and then a check on req.connection.destroyed. Is the same to do req.abort() and therefore checked as aforementioned req.aborted?
However I see that I mentioned the links in the code in link mentioned, which points to nodejs github source and its tests.
I recall that I tried to compare just like you did, (since we both did same, it's possible that it is correct, but I din't test it), but nodejs docs din't exactly mentioned that, at that time.
So, all I can say is,
we are talking about some documented and un-documented stuff
I have code mentioned in the link, running in production now, so possibly safe
(at least till something breaks in future release, if that is so the link I mentioned will not be saying so.)
Activity
neroux commentedon Mar 23, 2017
timeoutappears to refer to the connect timeout, not read timeoutSetting a timeout on the underlying socket might possibly work for you.
aleung commentedon Mar 24, 2017
@neroux As document says: it specifies the socket timeout. Socket timeouts after a duration of inactivity on the socket. It should cover both connect timeout and read timeout.
neroux commentedon Mar 24, 2017
The term socket timeout does not specify as to what times out. In this case it refers to the connection.
bnoordhuis commentedon Mar 24, 2017
What @neroux said. To set the read timeout, use
req.setTimeout(). Closing, working as documented and intended.aleung commentedon Mar 24, 2017
It makes me confusing.
@lpinca gives me comments in nock/nock#754 (comment) that it checks if there is socket activity for the whole duration of the request.
If it's as what @neroux said: it refers to the connection only, how to explain this code section which was committed in PR #8101 by @reneweb and PR #9440 by @italoacasas?
aleung commentedon Mar 24, 2017
To make sure, I have read through the source code net.js, _http_client.js and _http_agent.js.
First, when you call
socket.setTimeout()before a socket is connect, the idle timer is kept until the socket is destroyed orsetTimeout(0)is called. A socket won't clear its idle timer when it gets connect.The
timeoutparameter inoptionis passing through fromhttp.requesttohttp.Agent, then tonet.createConnectionand finally set onSocket. And I trace theconnectevent route and can't find any place that removes the timer.bnoordhuis commentedon Mar 24, 2017
Okay, I'll reopen. Asked the reviewers to chime in: #8101 (comment)
I'll note that the pull request has some red flags (trailing whitespace, long lines) that suggest it could have been scrutinized more.
mcollina commentedon Mar 24, 2017
I think this is a documentation problem more than a code problem. The PR does what is supposed to be doing. If we check https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback, the connection is not severed, but a
'timeout'event is emitted.This is what https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js#L25-L29 proves.
#9440 does its job at preventing the memory leak.
aleung commentedon Mar 25, 2017
@mcollina I'm not a native English speaker. Maybe I don't really understand this sentence:
It doesn't apear to me that after connection is established the idle timeout will be disabled.
Let's confirm with code:
After connection established, socket server delays 10 second to send data. Client sets timeout to 100ms and it gets timeout event.
From this test result on
net.Socket, it proves that socket timeout checks if there is socket activity for the whole duration of the connection.lpinca commentedon Mar 25, 2017
@aleung yes, that confirms what @mcollina wrote.
If the socket stays in idle for more than
timeouttime a'timeout'event will be emitted on the socket without closing (severing) the connection.aleung commentedon Mar 25, 2017
@lpinca Thanks for the explaination. However, I don't think I get an answer about whether my issue is valid or not.
My test case shows that
'timeout'event is not got onClientRequestwhen I usehttp.requestwithtimeoutoption. If I'm not using http but am using plain socket,'timeout'event is triggered on read timeout. The behaviour of usingtimeoutoption in these two scenrioes are different.Is it an issue on
httpmodule? Or it's intended? If it's intended, should the document ofhttp.requestbe updated to state that the timeout is only for connection estiblishing but not for read?Anyway, I believe when someone uses
http.requestand specfiestimeoutoption, what he expects is to capture any timeout on the request till it ends rather then only connection estiblishing.lpinca commentedon Mar 25, 2017
@aleung I think it works as expected. The
'timeout'event is correctly emitted. It's up to the developer to abort the request.Documentation should be updated to reflect the actual behavior though.
aleung commentedon Mar 25, 2017
Sorry everybody, I make a really stupid error in my test case: I want to listen on the
timeoutevent but I wroteerror.@lpinca thank you very much for your kindness answer.
manoharreddyporeddy commentedon Nov 29, 2017
Here is an working example:
https://stackoverflow.com/a/47546591/984471
loretoparisi commentedon Apr 6, 2018
@manoharreddyporeddy in that example I see
req.destroy();on timeout and then a check onreq.connection.destroyed. Is the same to doreq.abort()and therefore checked as aforementionedreq.aborted?manoharreddyporeddy commentedon Apr 6, 2018
I don't exactly recall what I wrote at that time.
However I see that I mentioned the links in the code in link mentioned, which points to nodejs github source and its tests.
I recall that I tried to compare just like you did, (since we both did same, it's possible that it is correct, but I din't test it), but nodejs docs din't exactly mentioned that, at that time.
So, all I can say is,
we are talking about some documented and un-documented stuff
I have code mentioned in the link, running in production now, so possibly safe
(at least till something breaks in future release, if that is so the link I mentioned will not be saying so.)