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
difference in timeout behavior between versions 0.18.1 and 0.19.0-2 #2710
Comments
Don't remember we changed something related to timeout. I saw it once in codesandbox and it can't be reproducible any more, no matter in local test or https://codesandbox.io/s/axios2710-bgphy. Can you confirm it is always the same result with different timeout values? |
Yes it is consistent for different values of timeout. However, the break in behavior seems to occur between 0.19.0 and 0.19.1 (i.e. the timeout value is respected for 0.19.0) |
@fresidue Can you provide the required information in the issue template? My codesandbox confirms your conclusion, which uses Node.js 10.17.0. But the local environment(OSX 10.14.5, Node.js 10.17.0) always works well. |
The timeout functionality breaks with https://github.com/axios/axios/pull/1752/files in axios v0.19.1 This is a pretty problematic bug. If URL is an IP address which is not reachable, the timeout will not be respected. |
@chinesedfan I'm running into this as well. I tried to provide the requested information below. Let me know if there is anything I can do to help get this fixed.
|
@fishcharlie According to @tblasche's discovery, it seems to be due to req.setTimeout. So this is an upstream problem. Can you or someone to check issues of Node.js? |
@chinesedfan I'm not finding anything on the Node.js issue section regarding this. I found a few similar things, but they didn't look like the same thing. I'd be happy to submit an issue and help try to move this forward. My only concern is that I don't have as much knowledge as some of the others here in terms of the story behind this issue an associated PR. I'm also not sure that we have a concrete failing example that is simple and easy to reproduce. Which makes it harder since anyone looking at the issue will have to dig through the axios codebase. Any thoughts on how to proceed? Would love to help get this fixed ASAP, but just want to make sure we are all on the same page, and I know I'm slightly more limited in my knowledge level about this. |
@fishcharlie That's really what we need. Once confirmed, we can open an issue to Node.js. The sample can be extracted from |
@chinesedfan I was only able to reproduce this error when using the NPM package nock, under very specific conditions. Took me a while to get a failing example. Below you can find the most minimal code I was able to use to recreate the problem. I attempted to create this also with an Express server that just doesn't send any response, and was unable to reproduce that. So I'm wondering if there is something else going on behind the scenes with like the connection or something. If you think this all looks good I will open an issue on the Let me know what your thoughts are. Working Code const http = require("http");
const nock = require("nock");
nock("http://test.com")
.persist()
.get("/test")
.reply(200, (a, b, c) => {});
const req = http.request("http://test.com/test", () => {
console.log("Response received");
});
setTimeout(() => {
req.abort();
console.error("Response timed out");
}, 5000); Failing Code const http = require("http");
const nock = require("nock");
nock("http://test.com")
.persist()
.get("/test")
.reply(200, (a, b, c) => {});
const req = http.request("http://test.com/test", () => {
console.log("Response received");
});
req.setTimeout(5000, () => {
req.abort();
console.error("Response timed out");
}); |
This issue is called as "Call Timeout". From request's README:
according to documentation:
so, if socket timeout is 1000ms and server sends packets per each 800ms, socket won't trigger timeout event. Here's quick reproducible codesandbox project: Please take a look into |
Quick & Dirty workaround at this moment: // Quick-and-dirty solution for call-timeout issue
// @see https://github.com/axios/axios/issues/2710
async function patchedAxios<T>(options: AxiosRequestConfig): Promise<AxiosResponse<T>> {
if (options.timeout) {
const cancelSource = axios.CancelToken.source();
const readTimeoutTimer = setTimeout(() => {
cancelSource.cancel(`timeout of ${options.timeout}ms exceeded`);
}, options.timeout);
try {
return await axios({
...options,
cancelToken: cancelSource.token,
});
} catch (e) {
if (axios.isCancel(e)) {
throw new Error(e.message);
}
throw e;
} finally {
clearTimeout(readTimeoutTimer);
}
} else {
return axios(options);
}
} |
@chinesedfan Wasn’t the reason for this change (and not using setTimeout/internal timers) due to a security vulnerability? Wouldn’t the code @mooyoul just suggested have that same security vulnerability? |
Another reproducible project: https://github.com/mooyoul/broken-axios-timeout |
@fishcharlie My workaround does not replace existing socket timeout handlers. To clarify, I'm not meaning that we should handle just single case. Connection Timeout can be handled by calling About "security vulnerability" that you've mentioned, I'm assuming that was caused by slow sockets. Slow sockets exhausted resources and blocked event loop. This issue was resolved by limiting connection timeouts as PR #1752 proposed. We just need to add internal timers to detect read timeout. |
@mooyoul Ahhh, got it. Is there a reason you think your workaround can't be turned into a PR on this main repo? |
@mooyoul If you think this is the correct path forward, I'd be happy to work on a PR and submit it to this repo. Let me know. Would love to get this fixed in a release so I don't have to use any workarounds or anything. |
@mooyoul @fishcharlie Really appreciated for your investigations. In summary, we should keep both of timers, right? Glad to see a PR with some tests. |
Yeah. I’m working on this issue and PR will be available in next few hours :) |
@mooyoul Awesome! Let me know if I can help at all!! Thanks for all the work you’ve put into this so far. |
@mooyoul Just wanted to check in and see if there was any updates on this. Is there any support I can provide in getting this across the finish line? |
Hello All, I've spent few hours to know how timeouts are actually handled in both XHR and Node.js built-in HTTPClient. Before starting a talk, I want to clarify variety types of timeouts. In general, There are a lot of timeout types: DNS Lookup Timeout"DNS Lookup Timeout" indicates that client submitted the query to the DNS server, It usually occurs when the DNS server you queried was having a problem and couldn't reply. Connect Timeout"Connect Timeout" indicates that client created socket and sent "TCP SYN" packet to server, You can quickly reproduce "Connect Timeout" by connecting to non-routable destination like It usually occurs when server firewall drops SYN packets. Bad network connectivity could be another reason as well.
Read Timeout"Read Timeout" indicates that time of inactivity between two data packets It usually occurs when server was super busy. Bad network condition could be another reason as well. Write Timeout"Write Timeout" indicates that time of inactivity between two data packets It usually occurs when server was super busy. Bad network condition could be another reason as well. Call Timeout"Call Timeout" indicates that "complete" HTTP call didn't completed in specified time. So many timeout types, right? I wanted to know how platforms actually handle these timeouts. and here are what i've found during experiment:
Luckily, In Node.js environment, Unsupported timeout types can be implemented from user-land (except connect timeout - it has a limitation of OS-wide setting). but In Browser environment, it cannot be implemented. So the problem is what we should choose - Keep idiomatic I'm not sure which way is the best - Please leave your thoughts! So at this moment, I'm opening a PR that just reverts previous changes, with additional tests. |
I just proposed PR #2874 @RikkiGibson @fishcharlie @chinesedfan Would you leave a feedback to upper comment? I want to hear your thoughts. Thanks! |
Hey, I just made my way here from the linked Nock issue. One thing I've noticed as missing from this thread is that when the change was made in 0.19.1, I don't know the internals of Axios that well, so I'm not sure if this helps at all, but it does explain why Nock's |
default headers are also not working in 0.18.1 following worked just fine
after updating to latest this no longer works |
Describe the bug
Using axios version 1.18.0, running the following mocha test, where the timeout is specified, results with:
Got the expected error: timeout of 200ms exceeded ✓ test axios (210ms) 1 passing (217ms)
Using axios version 1.19.x, running the same mocha test would result with
To Reproduce
run with mocha
Expected behavior
that the behavior from 0.18.0 would be preserved
The text was updated successfully, but these errors were encountered: