diff --git a/ehttp/src/lib.rs b/ehttp/src/lib.rs index 550b96e..61769c6 100644 --- a/ehttp/src/lib.rs +++ b/ehttp/src/lib.rs @@ -27,6 +27,7 @@ /// /// `Err` can happen for a number of reasons: /// * No internet connection +/// * Connection timed out /// * DNS resolution failed /// * Firewall or proxy blocked the request /// * Server is not reachable @@ -54,6 +55,7 @@ pub fn fetch(request: Request, on_done: impl 'static + Send + FnOnce(Result crate::Result { let mut req = ureq::request(&request.method, &request.url); + if let Some(timeout) = request.timeout { + req = req.timeout(timeout); + } + for (k, v) in &request.headers { req = req.set(k, v); } diff --git a/ehttp/src/types.rs b/ehttp/src/types.rs index 86b4557..b69de81 100644 --- a/ehttp/src/types.rs +++ b/ehttp/src/types.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + #[cfg(feature = "json")] use serde::Serialize; @@ -145,9 +147,14 @@ pub struct Request { /// /// Used on Web to control CORS. pub mode: Mode, + + /// Cancel the request if it doesn't complete fast enough. + pub timeout: Option, } impl Request { + pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30); + /// Create a `GET` request with the given url. #[allow(clippy::needless_pass_by_value)] pub fn get(url: impl ToString) -> Self { @@ -157,6 +164,7 @@ impl Request { body: vec![], headers: Headers::new(&[("Accept", "*/*")]), mode: Mode::default(), + timeout: Some(Self::DEFAULT_TIMEOUT), } } @@ -169,6 +177,7 @@ impl Request { body: vec![], headers: Headers::new(&[("Accept", "*/*")]), mode: Mode::default(), + timeout: Some(Self::DEFAULT_TIMEOUT), } } @@ -184,6 +193,7 @@ impl Request { ("Content-Type", "text/plain; charset=utf-8"), ]), mode: Mode::default(), + timeout: Some(Self::DEFAULT_TIMEOUT), } } @@ -209,6 +219,7 @@ impl Request { /// .unwrap(), /// ); /// ehttp::fetch(request, |result| {}); + /// ``` #[cfg(feature = "multipart")] pub fn multipart(url: impl ToString, builder: MultipartBuilder) -> Self { let (content_type, data) = builder.finish(); @@ -218,6 +229,7 @@ impl Request { body: data, headers: Headers::new(&[("Accept", "*/*"), ("Content-Type", content_type.as_str())]), mode: Mode::default(), + timeout: Some(Self::DEFAULT_TIMEOUT), } } @@ -234,8 +246,14 @@ impl Request { body: serde_json::to_string(body)?.into_bytes(), headers: Headers::new(&[("Accept", "*/*"), ("Content-Type", "application/json")]), mode: Mode::default(), + timeout: Some(Self::DEFAULT_TIMEOUT), }) } + + pub fn with_timeout(mut self, timeout: Option) -> Self { + self.timeout = timeout; + self + } } /// Response from a completed HTTP request. diff --git a/ehttp/src/web.rs b/ehttp/src/web.rs index 6057af4..8449d41 100644 --- a/ehttp/src/web.rs +++ b/ehttp/src/web.rs @@ -17,6 +17,7 @@ extern "C" { /// /// `Err` can happen for a number of reasons: /// * No internet connection +/// * Connection timed out /// * DNS resolution failed /// * Firewall or proxy blocked the request /// * Server is not reachable