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