feat(net): add socket timeouts to Server and Client
While these methods are marked unstable in libstd, this is behind a feature flag, `timeouts`. The Client and Server both have `set_read_timeout` and `set_write_timeout` methods, that will affect all connections with that entity. BREAKING CHANGE: Any custom implementation of NetworkStream must now implement `set_read_timeout` and `set_write_timeout`, so those will break. Most users who only use the provided streams should work with no changes needed. Closes #315
This commit is contained in:
		| @@ -59,13 +59,16 @@ use std::default::Default; | ||||
| use std::io::{self, copy, Read}; | ||||
| use std::iter::Extend; | ||||
|  | ||||
| #[cfg(feature = "timeouts")] | ||||
| use std::time::Duration; | ||||
|  | ||||
| use url::UrlParser; | ||||
| use url::ParseError as UrlError; | ||||
|  | ||||
| use header::{Headers, Header, HeaderFormat}; | ||||
| use header::{ContentLength, Location}; | ||||
| use method::Method; | ||||
| use net::{NetworkConnector, NetworkStream}; | ||||
| use net::{NetworkConnector, NetworkStream, Fresh}; | ||||
| use {Url}; | ||||
| use Error; | ||||
|  | ||||
| @@ -87,7 +90,9 @@ pub struct Client { | ||||
|     protocol: Box<Protocol + Send + Sync>, | ||||
|     redirect_policy: RedirectPolicy, | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     read_timeout: Option<Duration> | ||||
|     read_timeout: Option<Duration>, | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     write_timeout: Option<Duration>, | ||||
| } | ||||
|  | ||||
| impl Client { | ||||
| @@ -108,11 +113,23 @@ impl Client { | ||||
|         Client::with_protocol(Http11Protocol::with_connector(connector)) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "timeouts"))] | ||||
|     /// Create a new client with a specific `Protocol`. | ||||
|     pub fn with_protocol<P: Protocol + Send + Sync + 'static>(protocol: P) -> Client { | ||||
|         Client { | ||||
|             protocol: Box::new(protocol), | ||||
|             redirect_policy: Default::default() | ||||
|             redirect_policy: Default::default(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     /// Create a new client with a specific `Protocol`. | ||||
|     pub fn with_protocol<P: Protocol + Send + Sync + 'static>(protocol: P) -> Client { | ||||
|         Client { | ||||
|             protocol: Box::new(protocol), | ||||
|             redirect_policy: Default::default(), | ||||
|             read_timeout: None, | ||||
|             write_timeout: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -127,6 +144,12 @@ impl Client { | ||||
|         self.read_timeout = dur; | ||||
|     } | ||||
|  | ||||
|     /// Set the write timeout value for all requests. | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     pub fn set_write_timeout(&mut self, dur: Option<Duration>) { | ||||
|         self.write_timeout = dur; | ||||
|     } | ||||
|  | ||||
|     /// Build a Get request. | ||||
|     pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder<U> { | ||||
|         self.request(Method::Get, url) | ||||
| @@ -236,6 +259,20 @@ impl<'a, U: IntoUrl> RequestBuilder<'a, U> { | ||||
|             let mut req = try!(Request::with_message(method.clone(), url.clone(), message)); | ||||
|             headers.as_ref().map(|headers| req.headers_mut().extend(headers.iter())); | ||||
|  | ||||
|             #[cfg(not(feature = "timeouts"))] | ||||
|             fn set_timeouts(_req: &mut Request<Fresh>, _client: &Client) -> ::Result<()> { | ||||
|                 Ok(()) | ||||
|             } | ||||
|  | ||||
|             #[cfg(feature = "timeouts")] | ||||
|             fn set_timeouts(req: &mut Request<Fresh>, client: &Client) -> ::Result<()> { | ||||
|                 try!(req.set_write_timeout(client.write_timeout)); | ||||
|                 try!(req.set_read_timeout(client.read_timeout)); | ||||
|                 Ok(()) | ||||
|             } | ||||
|  | ||||
|             try!(set_timeouts(&mut req, &client)); | ||||
|  | ||||
|             match (can_have_body, body.as_ref()) { | ||||
|                 (true, Some(body)) => match body.size() { | ||||
|                     Some(size) => req.headers_mut().set(ContentLength(size)), | ||||
|   | ||||
| @@ -5,6 +5,9 @@ use std::io::{self, Read, Write}; | ||||
| use std::net::{SocketAddr, Shutdown}; | ||||
| use std::sync::{Arc, Mutex}; | ||||
|  | ||||
| #[cfg(feature = "timeouts")] | ||||
| use std::time::Duration; | ||||
|  | ||||
| use net::{NetworkConnector, NetworkStream, DefaultConnector}; | ||||
|  | ||||
| /// The `NetworkConnector` that behaves as a connection pool used by hyper's `Client`. | ||||
| @@ -153,6 +156,18 @@ impl<S: NetworkStream> NetworkStream for PooledStream<S> { | ||||
|         self.inner.as_mut().unwrap().1.peer_addr() | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     #[inline] | ||||
|     fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | ||||
|         self.inner.as_ref().unwrap().1.set_read_timeout(dur) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     #[inline] | ||||
|     fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | ||||
|         self.inner.as_ref().unwrap().1.set_write_timeout(dur) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn close(&mut self, how: Shutdown) -> io::Result<()> { | ||||
|         self.is_closed = true; | ||||
|   | ||||
| @@ -2,6 +2,9 @@ | ||||
| use std::marker::PhantomData; | ||||
| use std::io::{self, Write}; | ||||
|  | ||||
| #[cfg(feature = "timeouts")] | ||||
| use std::time::Duration; | ||||
|  | ||||
| use url::Url; | ||||
|  | ||||
| use method::{self, Method}; | ||||
| @@ -39,6 +42,20 @@ impl<W> Request<W> { | ||||
|     /// Read the Request method. | ||||
|     #[inline] | ||||
|     pub fn method(&self) -> method::Method { self.method.clone() } | ||||
|  | ||||
|     /// Set the write timeout. | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     #[inline] | ||||
|     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | ||||
|         self.message.set_write_timeout(dur) | ||||
|     } | ||||
|  | ||||
|     /// Set the read timeout. | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     #[inline] | ||||
|     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | ||||
|         self.message.set_read_timeout(dur) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Request<Fresh> { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user