Provide request timeout for blocking API (#764)
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							b159963f6c
						
					
				
				
					commit
					22fe6566ff
				
			| @@ -670,6 +670,8 @@ impl ClientHandle { | ||||
|         let (tx, rx) = oneshot::channel(); | ||||
|         let (req, body) = req.into_async(); | ||||
|         let url = req.url().clone(); | ||||
|         let timeout = req.timeout().copied().or(self.timeout.0); | ||||
|  | ||||
|         self.inner | ||||
|             .tx | ||||
|             .as_ref() | ||||
| @@ -683,12 +685,12 @@ impl ClientHandle { | ||||
|                     body.send().await?; | ||||
|                     rx.await.map_err(|_canceled| event_loop_panicked()) | ||||
|                 }; | ||||
|                 wait::timeout(f, self.timeout.0) | ||||
|                 wait::timeout(f, timeout) | ||||
|             } else { | ||||
|                 let f = async move { | ||||
|                     rx.await.map_err(|_canceled| event_loop_panicked()) | ||||
|                 }; | ||||
|                 wait::timeout(f, self.timeout.0) | ||||
|                 wait::timeout(f, timeout) | ||||
|             }; | ||||
|  | ||||
|         match result { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| use std::fmt; | ||||
| use std::convert::TryFrom; | ||||
| use std::time::Duration; | ||||
|  | ||||
| use base64::encode; | ||||
| use serde::Serialize; | ||||
| @@ -84,6 +85,18 @@ impl Request { | ||||
|         &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`. | ||||
|     /// | ||||
|     /// 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 | ||||
|     } | ||||
|  | ||||
|     /// 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. | ||||
|     /// | ||||
|     /// 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())); | ||||
| } | ||||
|  | ||||
| #[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")] | ||||
| #[test] | ||||
| fn write_timeout_large_body() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user