Skip to content

Commit

Permalink
Fixing timeout detection in Node.js environment
Browse files Browse the repository at this point in the history
Fixes axios#2710
Reverts axios#1752
  • Loading branch information
mooyoul committed Apr 6, 2020
1 parent 5e0fb5f commit 005e2bf
Showing 1 changed file with 18 additions and 8 deletions.
26 changes: 18 additions & 8 deletions lib/adapters/http.js
Expand Up @@ -19,10 +19,14 @@ var isHttps = /https:?/;
/*eslint consistent-return:0*/
module.exports = function httpAdapter(config) {
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
var timer;

var resolve = function resolve(value) {
clearTimeout(timer);
resolvePromise(value);
};
var reject = function reject(value) {
clearTimeout(timer);
rejectPromise(value);
};
var data = config.data;
Expand Down Expand Up @@ -250,16 +254,22 @@ module.exports = function httpAdapter(config) {
});

// Handle request timeout
//
// There are many types of timeouts:
// DNS Timeout, Connect Timeout, Read/Write Timeout (idle timeout), and Call Timeout.
// Call Timeout measures from DNS Lookup to response body receiving completion.
//
// Currently, `timeout` option in Browser XHR indicates "Call Timeout".
// Create internal timer to match browser-side behavior.
if (config.timeout) {
// Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
// And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
// At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
// And then these socket which be hang up will devoring CPU little by little.
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
req.setTimeout(config.timeout, function handleRequestTimeout() {
// Set internal timer to detect "Call Timeout"
// @see https://github.com/axios/axios/issues/2710#issuecomment-605693456
timer = setTimeout(function handleReadTimeout() {
// Stop receiving remaining bytes and close socket
req.abort();
reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));
});

reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ETIMEDOUT', req));
}, config.timeout);
}

if (config.cancelToken) {
Expand Down

0 comments on commit 005e2bf

Please sign in to comment.