Provide request timeout for blocking API (#764)
This commit is contained in:
committed by
Sean McArthur
parent
b159963f6c
commit
22fe6566ff
@@ -670,6 +670,8 @@ impl ClientHandle {
|
|||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let (req, body) = req.into_async();
|
let (req, body) = req.into_async();
|
||||||
let url = req.url().clone();
|
let url = req.url().clone();
|
||||||
|
let timeout = req.timeout().copied().or(self.timeout.0);
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
.tx
|
.tx
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -683,12 +685,12 @@ impl ClientHandle {
|
|||||||
body.send().await?;
|
body.send().await?;
|
||||||
rx.await.map_err(|_canceled| event_loop_panicked())
|
rx.await.map_err(|_canceled| event_loop_panicked())
|
||||||
};
|
};
|
||||||
wait::timeout(f, self.timeout.0)
|
wait::timeout(f, timeout)
|
||||||
} else {
|
} else {
|
||||||
let f = async move {
|
let f = async move {
|
||||||
rx.await.map_err(|_canceled| event_loop_panicked())
|
rx.await.map_err(|_canceled| event_loop_panicked())
|
||||||
};
|
};
|
||||||
wait::timeout(f, self.timeout.0)
|
wait::timeout(f, timeout)
|
||||||
};
|
};
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use base64::encode;
|
use base64::encode;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -84,6 +85,18 @@ impl Request {
|
|||||||
&mut self.body
|
&mut self.body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the timeout.
|
||||||
|
#[inline]
|
||||||
|
pub fn timeout(&self) -> Option<&Duration> {
|
||||||
|
self.inner.timeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the timeout.
|
||||||
|
#[inline]
|
||||||
|
pub fn timeout_mut(&mut self) -> &mut Option<Duration> {
|
||||||
|
self.inner.timeout_mut()
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempts to clone the `Request`.
|
/// Attempts to clone the `Request`.
|
||||||
///
|
///
|
||||||
/// None is returned if a body is which can not be cloned. This can be because the body is a
|
/// None is returned if a body is which can not be cloned. This can be because the body is a
|
||||||
@@ -300,6 +313,18 @@ impl RequestBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables a request timeout.
|
||||||
|
///
|
||||||
|
/// The timeout is applied from the when the request starts connecting
|
||||||
|
/// until the response body has finished. It affects only this request
|
||||||
|
/// and overrides the timeout configured using `ClientBuilder::timeout()`.
|
||||||
|
pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {
|
||||||
|
if let Ok(ref mut req) = self.request {
|
||||||
|
*req.timeout_mut() = Some(timeout);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Modify the query string of the URL.
|
/// Modify the query string of the URL.
|
||||||
///
|
///
|
||||||
/// Modifies the URL of this request, adding the parameters provided.
|
/// Modifies the URL of this request, adding the parameters provided.
|
||||||
|
|||||||
@@ -117,6 +117,34 @@ fn timeout_closes_connection() {
|
|||||||
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
|
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
#[test]
|
||||||
|
fn timeout_blocking_request() {
|
||||||
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
|
// Make Client drop *after* the Server, so the background doesn't
|
||||||
|
// close too early.
|
||||||
|
let client = reqwest::blocking::Client::builder().build().unwrap();
|
||||||
|
|
||||||
|
let server = server::http(move |_req| {
|
||||||
|
async {
|
||||||
|
// delay returning the response
|
||||||
|
tokio::time::delay_for(Duration::from_secs(2)).await;
|
||||||
|
http::Response::default()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let url = format!("http://{}/closes", server.addr());
|
||||||
|
let err = client
|
||||||
|
.get(&url)
|
||||||
|
.timeout(Duration::from_millis(500))
|
||||||
|
.send()
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(err.is_timeout());
|
||||||
|
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "blocking")]
|
#[cfg(feature = "blocking")]
|
||||||
#[test]
|
#[test]
|
||||||
fn write_timeout_large_body() {
|
fn write_timeout_large_body() {
|
||||||
|
|||||||
Reference in New Issue
Block a user