From 6d9d31cad13cb0314a94b31c92b474e1d0c57a86 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Wed, 11 Jan 2023 11:55:42 -0300 Subject: [PATCH] Add timeouts to HTTP requests (#3908) --- CHANGELOG.md | 1 + src/configure/read_url.rs | 2 +- src/http.rs | 12 ++++++++++++ src/lib.rs | 1 + src/oauth2.rs | 11 +++++++++-- src/qr.rs | 2 +- 6 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/http.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef009c26..f36e6cf43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - fix: only send contact changed event for recently seen if it is relevant (not too old to matter) #3938 - Immediately save `accounts.toml` if it was modified by a migration from absolute paths to relative paths #3943 - Do not treat invalid email addresses as an exception #3942 +- Add timeouts to HTTP requests #3948 ## 1.105.0 diff --git a/src/configure/read_url.rs b/src/configure/read_url.rs index f275025db..b0cdd989f 100644 --- a/src/configure/read_url.rs +++ b/src/configure/read_url.rs @@ -16,7 +16,7 @@ pub async fn read_url(context: &Context, url: &str) -> anyhow::Result { } pub async fn read_url_inner(context: &Context, url: &str) -> anyhow::Result { - let client = reqwest::Client::new(); + let client = crate::http::get_client()?; let mut url = url.to_string(); // Follow up to 10 http-redirects diff --git a/src/http.rs b/src/http.rs new file mode 100644 index 000000000..4f0c3fb35 --- /dev/null +++ b/src/http.rs @@ -0,0 +1,12 @@ +//! # HTTP module. + +use anyhow::Result; +use std::time::Duration; + +const HTTP_TIMEOUT: Duration = Duration::from_secs(30); + +pub(crate) fn get_client() -> Result { + Ok(reqwest::ClientBuilder::new() + .timeout(HTTP_TIMEOUT) + .build()?) +} diff --git a/src/lib.rs b/src/lib.rs index a6e8eb8ae..831f6609e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ mod decrypt; pub mod download; mod e2ee; pub mod ephemeral; +mod http; mod imap; pub mod imex; mod scheduler; diff --git a/src/oauth2.rs b/src/oauth2.rs index d48cb45a6..ab0b4eef5 100644 --- a/src/oauth2.rs +++ b/src/oauth2.rs @@ -158,7 +158,7 @@ pub async fn get_oauth2_access_token( } // ... and POST - let client = reqwest::Client::new(); + let client = crate::http::get_client()?; let response: Response = match client.post(post_url).form(&post_param).send().await { Ok(resp) => match resp.json().await { @@ -284,7 +284,14 @@ impl Oauth2 { // "verified_email": true, // "picture": "https://lh4.googleusercontent.com/-Gj5jh_9R0BY/AAAAAAAAAAI/AAAAAAAAAAA/IAjtjfjtjNA/photo.jpg" // } - let response = match reqwest::get(userinfo_url).await { + let client = match crate::http::get_client() { + Ok(cl) => cl, + Err(err) => { + warn!(context, "failed to get HTTP client: {}", err); + return None; + } + }; + let response = match client.get(userinfo_url).send().await { Ok(response) => response, Err(err) => { warn!(context, "failed to get userinfo: {}", err); diff --git a/src/qr.rs b/src/qr.rs index c1e250211..7cd4fc28c 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -381,7 +381,7 @@ struct CreateAccountErrorResponse { #[allow(clippy::indexing_slicing)] async fn set_account_from_qr(context: &Context, qr: &str) -> Result<()> { let url_str = &qr[DCACCOUNT_SCHEME.len()..]; - let response = reqwest::Client::new().post(url_str).send().await?; + let response = crate::http::get_client()?.post(url_str).send().await?; let response_status = response.status(); let response_text = response.text().await.with_context(|| { format!(