mirror of
https://github.com/chatmail/core.git
synced 2026-04-18 05:56:31 +03:00
fix(http): set I/O timeout to 1 minute rather than whole request timeout
Before the fix HTTP client had no connection timeout, so it only had a chance to test one IPv6 and one IPv4 address if the first addresses timed out. Now it can test at least 4 addresses of each family and more if some addresses refuse connection rather than time out.
This commit is contained in:
@@ -27,6 +27,13 @@ use tls::wrap_tls;
|
||||
/// This constant should be more than the largest expected RTT.
|
||||
pub(crate) const TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
/// Transaction timeout, e.g. for a GET or POST request
|
||||
/// together with all connection attempts.
|
||||
///
|
||||
/// This is the worst case time user has to wait on a very slow network
|
||||
/// after clicking a button and before getting an error message.
|
||||
pub(crate) const TRANSACTION_TIMEOUT: Duration = Duration::from_secs(300);
|
||||
|
||||
/// TTL for caches in seconds.
|
||||
pub(crate) const CACHE_TTL: u64 = 30 * 24 * 60 * 60;
|
||||
|
||||
|
||||
@@ -136,8 +136,24 @@ pub(crate) async fn get_client(context: &Context, load_cache: bool) -> Result<re
|
||||
let socks5_config = Socks5Config::from_database(&context.sql).await?;
|
||||
let resolver = Arc::new(CustomResolver::new(context.clone(), load_cache));
|
||||
|
||||
// `reqwest` uses `hyper-util` crate internally which implements
|
||||
// [Happy Eyeballs](https://datatracker.ietf.org/doc/html/rfc6555) algorithm.
|
||||
// On a dual-stack host it starts IPv4 connection attempts in parallel
|
||||
// to IPv6 connection attempts after 300 ms.
|
||||
// In the worst case of all connection attempts
|
||||
// timing out this allows to try four IPv6 and four IPv4
|
||||
// addresses before request expires
|
||||
// if request timeout is set to 5 minutes
|
||||
// and connection timeout is set to 1 minute.
|
||||
//
|
||||
// We do not set write timeout because `reqwest`
|
||||
// does not support it, but request timeout
|
||||
// should prevent deadlocks if the server
|
||||
// does not read the data.
|
||||
let builder = reqwest::ClientBuilder::new()
|
||||
.timeout(super::TIMEOUT)
|
||||
.connect_timeout(super::TIMEOUT)
|
||||
.read_timeout(super::TIMEOUT)
|
||||
.timeout(super::TRANSACTION_TIMEOUT)
|
||||
.add_root_certificate(LETSENCRYPT_ROOT.clone())
|
||||
.dns_resolver(resolver);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user