Merge pull request #428 from hyperium/client-box
feat(client): remove generic parameter for Connector
This commit is contained in:
		| @@ -27,7 +27,7 @@ use url::ParseError as UrlError; | |||||||
| use header::{Headers, Header, HeaderFormat}; | use header::{Headers, Header, HeaderFormat}; | ||||||
| use header::{ContentLength, Location}; | use header::{ContentLength, Location}; | ||||||
| use method::Method; | use method::Method; | ||||||
| use net::{NetworkConnector, HttpConnector, ContextVerifier}; | use net::{NetworkConnector, NetworkStream, HttpConnector, ContextVerifier}; | ||||||
| use status::StatusClass::Redirection; | use status::StatusClass::Redirection; | ||||||
| use {Url, HttpResult}; | use {Url, HttpResult}; | ||||||
| use HttpError::HttpUriError; | use HttpError::HttpUriError; | ||||||
| @@ -41,68 +41,65 @@ pub mod response; | |||||||
| /// A Client to use additional features with Requests. | /// A Client to use additional features with Requests. | ||||||
| /// | /// | ||||||
| /// Clients can handle things such as: redirect policy. | /// Clients can handle things such as: redirect policy. | ||||||
| pub struct Client<C> { | pub struct Client { | ||||||
|     connector: C, |     connector: Connector, | ||||||
|     redirect_policy: RedirectPolicy, |     redirect_policy: RedirectPolicy, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'v> Client<HttpConnector<'v>> { | impl Client { | ||||||
|  |  | ||||||
|     /// Create a new Client. |     /// Create a new Client. | ||||||
|     pub fn new() -> Client<HttpConnector<'v>> { |     pub fn new() -> Client { | ||||||
|         Client::with_connector(HttpConnector(None)) |         Client::with_connector(HttpConnector(None)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Set the SSL verifier callback for use with OpenSSL. |  | ||||||
|     pub fn set_ssl_verifier(&mut self, verifier: ContextVerifier<'v>) { |  | ||||||
|         self.connector = HttpConnector(Some(verifier)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<C: NetworkConnector> Client<C> { |  | ||||||
|  |  | ||||||
|     /// Create a new client with a specific connector. |     /// Create a new client with a specific connector. | ||||||
|     pub fn with_connector(connector: C) -> Client<C> { |     pub fn with_connector<C, S>(connector: C) -> Client | ||||||
|  |     where C: NetworkConnector<Stream=S> + Send + 'static, S: NetworkStream + Send { | ||||||
|         Client { |         Client { | ||||||
|             connector: connector, |             connector: with_connector(connector), | ||||||
|             redirect_policy: Default::default() |             redirect_policy: Default::default() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Set the SSL verifier callback for use with OpenSSL. | ||||||
|  |     pub fn set_ssl_verifier(&mut self, verifier: ContextVerifier) { | ||||||
|  |         self.connector = with_connector(HttpConnector(Some(verifier))); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Set the RedirectPolicy. |     /// Set the RedirectPolicy. | ||||||
|     pub fn set_redirect_policy(&mut self, policy: RedirectPolicy) { |     pub fn set_redirect_policy(&mut self, policy: RedirectPolicy) { | ||||||
|         self.redirect_policy = policy; |         self.redirect_policy = policy; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Build a Get request. |     /// Build a Get request. | ||||||
|     pub fn get<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> { |     pub fn get<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> { | ||||||
|         self.request(Method::Get, url) |         self.request(Method::Get, url) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Build a Head request. |     /// Build a Head request. | ||||||
|     pub fn head<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> { |     pub fn head<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> { | ||||||
|         self.request(Method::Head, url) |         self.request(Method::Head, url) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Build a Post request. |     /// Build a Post request. | ||||||
|     pub fn post<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> { |     pub fn post<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> { | ||||||
|         self.request(Method::Post, url) |         self.request(Method::Post, url) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Build a Put request. |     /// Build a Put request. | ||||||
|     pub fn put<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> { |     pub fn put<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> { | ||||||
|         self.request(Method::Put, url) |         self.request(Method::Put, url) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Build a Delete request. |     /// Build a Delete request. | ||||||
|     pub fn delete<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> { |     pub fn delete<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> { | ||||||
|         self.request(Method::Delete, url) |         self.request(Method::Delete, url) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /// Build a new request using this Client. |     /// Build a new request using this Client. | ||||||
|     pub fn request<U: IntoUrl>(&mut self, method: Method, url: U) -> RequestBuilder<U, C> { |     pub fn request<U: IntoUrl>(&mut self, method: Method, url: U) -> RequestBuilder<U> { | ||||||
|         RequestBuilder { |         RequestBuilder { | ||||||
|             client: self, |             client: self, | ||||||
|             method: method, |             method: method, | ||||||
| @@ -113,34 +110,60 @@ impl<C: NetworkConnector> Client<C> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn with_connector<C: NetworkConnector<Stream=S> + Send + 'static, S: NetworkStream + Send>(c: C) -> Connector { | ||||||
|  |     Connector(Box::new(ConnAdapter(c))) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct ConnAdapter<C: NetworkConnector + Send>(C); | ||||||
|  |  | ||||||
|  | impl<C: NetworkConnector<Stream=S> + Send, S: NetworkStream + Send> NetworkConnector for ConnAdapter<C> { | ||||||
|  |     type Stream = Box<NetworkStream + Send>; | ||||||
|  |     #[inline] | ||||||
|  |     fn connect(&mut self, host: &str, port: u16, scheme: &str) | ||||||
|  |         -> io::Result<Box<NetworkStream + Send>> { | ||||||
|  |         Ok(try!(self.0.connect(host, port, scheme)).into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct Connector(Box<NetworkConnector<Stream=Box<NetworkStream + Send>> + Send>); | ||||||
|  |  | ||||||
|  | impl NetworkConnector for Connector { | ||||||
|  |     type Stream = Box<NetworkStream + Send>; | ||||||
|  |     #[inline] | ||||||
|  |     fn connect(&mut self, host: &str, port: u16, scheme: &str) | ||||||
|  |         -> io::Result<Box<NetworkStream + Send>> { | ||||||
|  |         Ok(try!(self.0.connect(host, port, scheme)).into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Options for an individual Request. | /// Options for an individual Request. | ||||||
| /// | /// | ||||||
| /// One of these will be built for you if you use one of the convenience | /// One of these will be built for you if you use one of the convenience | ||||||
| /// methods, such as `get()`, `post()`, etc. | /// methods, such as `get()`, `post()`, etc. | ||||||
| pub struct RequestBuilder<'a, U: IntoUrl, C: NetworkConnector + 'a> { | pub struct RequestBuilder<'a, U: IntoUrl> { | ||||||
|     client: &'a mut Client<C>, |     client: &'a mut Client, | ||||||
|     url: U, |     url: U, | ||||||
|     headers: Option<Headers>, |     headers: Option<Headers>, | ||||||
|     method: Method, |     method: Method, | ||||||
|     body: Option<Body<'a>>, |     body: Option<Body<'a>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'a, U: IntoUrl, C: NetworkConnector> RequestBuilder<'a, U, C> { | impl<'a, U: IntoUrl> RequestBuilder<'a, U> { | ||||||
|  |  | ||||||
|     /// Set a request body to be sent. |     /// Set a request body to be sent. | ||||||
|     pub fn body<B: IntoBody<'a>>(mut self, body: B) -> RequestBuilder<'a, U, C> { |     pub fn body<B: IntoBody<'a>>(mut self, body: B) -> RequestBuilder<'a, U> { | ||||||
|         self.body = Some(body.into_body()); |         self.body = Some(body.into_body()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Add additional headers to the request. |     /// Add additional headers to the request. | ||||||
|     pub fn headers(mut self, headers: Headers) -> RequestBuilder<'a, U, C> { |     pub fn headers(mut self, headers: Headers) -> RequestBuilder<'a, U> { | ||||||
|         self.headers = Some(headers); |         self.headers = Some(headers); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Add an individual new header to the request. |     /// Add an individual new header to the request. | ||||||
|     pub fn header<H: Header + HeaderFormat>(mut self, header: H) -> RequestBuilder<'a, U, C> { |     pub fn header<H: Header + HeaderFormat>(mut self, header: H) -> RequestBuilder<'a, U> { | ||||||
|         { |         { | ||||||
|             let mut headers = match self.headers { |             let mut headers = match self.headers { | ||||||
|                 Some(ref mut h) => h, |                 Some(ref mut h) => h, | ||||||
|   | |||||||
| @@ -51,13 +51,11 @@ impl Request<Fresh> { | |||||||
|     pub fn with_connector<C, S>(method: method::Method, url: Url, connector: &mut C) |     pub fn with_connector<C, S>(method: method::Method, url: Url, connector: &mut C) | ||||||
|         -> HttpResult<Request<Fresh>> where |         -> HttpResult<Request<Fresh>> where | ||||||
|         C: NetworkConnector<Stream=S>, |         C: NetworkConnector<Stream=S>, | ||||||
|         S: NetworkStream + Send { |         S: Into<Box<NetworkStream + Send>> { | ||||||
|         debug!("{} {}", method, url); |         debug!("{} {}", method, url); | ||||||
|         let (host, port) = try!(get_host_and_port(&url)); |         let (host, port) = try!(get_host_and_port(&url)); | ||||||
|  |  | ||||||
|         let stream = try!(connector.connect(&*host, port, &*url.scheme)); |         let stream = try!(connector.connect(&*host, port, &*url.scheme)).into(); | ||||||
|         // FIXME: Use Type ascription |  | ||||||
|         let stream: Box<NetworkStream + Send> = Box::new(stream); |  | ||||||
|         let stream = ThroughWriter(BufWriter::new(stream)); |         let stream = ThroughWriter(BufWriter::new(stream)); | ||||||
|  |  | ||||||
|         let mut headers = Headers::new(); |         let mut headers = Headers::new(); | ||||||
|   | |||||||
| @@ -190,6 +190,7 @@ mod mimewrapper { | |||||||
|  |  | ||||||
| #[allow(unconditional_recursion)] | #[allow(unconditional_recursion)] | ||||||
| fn _assert_send<T: Send>() { | fn _assert_send<T: Send>() { | ||||||
|  |     _assert_send::<Client>(); | ||||||
|     _assert_send::<client::Request<net::Fresh>>(); |     _assert_send::<client::Request<net::Fresh>>(); | ||||||
|     _assert_send::<client::Response>(); |     _assert_send::<client::Response>(); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/net.rs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/net.rs
									
									
									
									
									
								
							| @@ -75,11 +75,17 @@ impl<T: NetworkStream + Send + Clone> StreamClone for T { | |||||||
| /// A connector creates a NetworkStream. | /// A connector creates a NetworkStream. | ||||||
| pub trait NetworkConnector { | pub trait NetworkConnector { | ||||||
|     /// Type of Stream to create |     /// Type of Stream to create | ||||||
|     type Stream: NetworkStream + Send; |     type Stream: Into<Box<NetworkStream + Send>>; | ||||||
|     /// Connect to a remote address. |     /// Connect to a remote address. | ||||||
|     fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<Self::Stream>; |     fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<Self::Stream>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl<T: NetworkStream + Send> From<T> for Box<NetworkStream + Send> { | ||||||
|  |     fn from(s: T) -> Box<NetworkStream + Send> { | ||||||
|  |         Box::new(s) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| impl fmt::Debug for Box<NetworkStream + Send> { | impl fmt::Debug for Box<NetworkStream + Send> { | ||||||
|     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         fmt.pad("Box<NetworkStream>") |         fmt.pad("Box<NetworkStream>") | ||||||
| @@ -284,13 +290,12 @@ impl NetworkStream for HttpStream { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// A connector that will produce HttpStreams. | /// A connector that will produce HttpStreams. | ||||||
| #[allow(missing_copy_implementations)] | pub struct HttpConnector(pub Option<ContextVerifier>); | ||||||
| pub struct HttpConnector<'v>(pub Option<ContextVerifier<'v>>); |  | ||||||
|  |  | ||||||
| /// A method that can set verification methods on an SSL context | /// A method that can set verification methods on an SSL context | ||||||
| pub type ContextVerifier<'v> = Box<FnMut(&mut SslContext) -> ()+'v>; | pub type ContextVerifier = Box<FnMut(&mut SslContext) -> () + Send>; | ||||||
|  |  | ||||||
| impl<'v> NetworkConnector for HttpConnector<'v> { | impl NetworkConnector for HttpConnector { | ||||||
|     type Stream = HttpStream; |     type Stream = HttpStream; | ||||||
|  |  | ||||||
|     fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<HttpStream> { |     fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<HttpStream> { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user