Skip to content

Commit 139a51f

Browse files
committed
feat(client): remove generic parameter for Connector
Closes #379 BREAKING CHANGE: For people using the default HttpConnector and Client, everything should continue to just work. If the Client has been used with a generic parameter, it should be removed. However, there were some breaking changes to the internals of NetworkConnectors. Specifically, they no longer return a NetworkStream, but instead a Into<Box<NetworkStream + Send>>. All implementations of NetworkStream should continue to just work, however. Possible breakages could come from the stricter usage of Send throughout the Client API.
1 parent 4fecd64 commit 139a51f

File tree

4 files changed

+64
-37
lines changed

4 files changed

+64
-37
lines changed

src/client/mod.rs

+51-28
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use url::ParseError as UrlError;
2727
use header::{Headers, Header, HeaderFormat};
2828
use header::{ContentLength, Location};
2929
use method::Method;
30-
use net::{NetworkConnector, HttpConnector, ContextVerifier};
30+
use net::{NetworkConnector, NetworkStream, HttpConnector, ContextVerifier};
3131
use status::StatusClass::Redirection;
3232
use {Url, HttpResult};
3333
use HttpError::HttpUriError;
@@ -41,68 +41,65 @@ pub mod response;
4141
/// A Client to use additional features with Requests.
4242
///
4343
/// Clients can handle things such as: redirect policy.
44-
pub struct Client<C> {
45-
connector: C,
44+
pub struct Client {
45+
connector: Connector,
4646
redirect_policy: RedirectPolicy,
4747
}
4848

49-
impl<'v> Client<HttpConnector<'v>> {
49+
impl Client {
5050

5151
/// Create a new Client.
52-
pub fn new() -> Client<HttpConnector<'v>> {
52+
pub fn new() -> Client {
5353
Client::with_connector(HttpConnector(None))
5454
}
5555

56-
/// Set the SSL verifier callback for use with OpenSSL.
57-
pub fn set_ssl_verifier(&mut self, verifier: ContextVerifier<'v>) {
58-
self.connector = HttpConnector(Some(verifier));
59-
}
60-
61-
}
62-
63-
impl<C: NetworkConnector> Client<C> {
64-
6556
/// Create a new client with a specific connector.
66-
pub fn with_connector(connector: C) -> Client<C> {
57+
pub fn with_connector<C, S>(connector: C) -> Client
58+
where C: NetworkConnector<Stream=S> + Send + 'static, S: NetworkStream + Send {
6759
Client {
68-
connector: connector,
60+
connector: with_connector(connector),
6961
redirect_policy: Default::default()
7062
}
7163
}
7264

65+
/// Set the SSL verifier callback for use with OpenSSL.
66+
pub fn set_ssl_verifier(&mut self, verifier: ContextVerifier) {
67+
self.connector = with_connector(HttpConnector(Some(verifier)));
68+
}
69+
7370
/// Set the RedirectPolicy.
7471
pub fn set_redirect_policy(&mut self, policy: RedirectPolicy) {
7572
self.redirect_policy = policy;
7673
}
7774

7875
/// Build a Get request.
79-
pub fn get<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> {
76+
pub fn get<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> {
8077
self.request(Method::Get, url)
8178
}
8279

8380
/// Build a Head request.
84-
pub fn head<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> {
81+
pub fn head<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> {
8582
self.request(Method::Head, url)
8683
}
8784

8885
/// Build a Post request.
89-
pub fn post<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> {
86+
pub fn post<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> {
9087
self.request(Method::Post, url)
9188
}
9289

9390
/// Build a Put request.
94-
pub fn put<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> {
91+
pub fn put<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> {
9592
self.request(Method::Put, url)
9693
}
9794

9895
/// Build a Delete request.
99-
pub fn delete<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U, C> {
96+
pub fn delete<U: IntoUrl>(&mut self, url: U) -> RequestBuilder<U> {
10097
self.request(Method::Delete, url)
10198
}
10299

103100

104101
/// Build a new request using this Client.
105-
pub fn request<U: IntoUrl>(&mut self, method: Method, url: U) -> RequestBuilder<U, C> {
102+
pub fn request<U: IntoUrl>(&mut self, method: Method, url: U) -> RequestBuilder<U> {
106103
RequestBuilder {
107104
client: self,
108105
method: method,
@@ -113,34 +110,60 @@ impl<C: NetworkConnector> Client<C> {
113110
}
114111
}
115112

113+
fn with_connector<C: NetworkConnector<Stream=S> + Send + 'static, S: NetworkStream + Send>(c: C) -> Connector {
114+
Connector(Box::new(ConnAdapter(c)))
115+
}
116+
117+
struct ConnAdapter<C: NetworkConnector + Send>(C);
118+
119+
impl<C: NetworkConnector<Stream=S> + Send, S: NetworkStream + Send> NetworkConnector for ConnAdapter<C> {
120+
type Stream = Box<NetworkStream + Send>;
121+
#[inline]
122+
fn connect(&mut self, host: &str, port: u16, scheme: &str)
123+
-> io::Result<Box<NetworkStream + Send>> {
124+
Ok(try!(self.0.connect(host, port, scheme)).into())
125+
}
126+
}
127+
128+
struct Connector(Box<NetworkConnector<Stream=Box<NetworkStream + Send>> + Send>);
129+
130+
impl NetworkConnector for Connector {
131+
type Stream = Box<NetworkStream + Send>;
132+
#[inline]
133+
fn connect(&mut self, host: &str, port: u16, scheme: &str)
134+
-> io::Result<Box<NetworkStream + Send>> {
135+
Ok(try!(self.0.connect(host, port, scheme)).into())
136+
}
137+
}
138+
116139
/// Options for an individual Request.
117140
///
118141
/// One of these will be built for you if you use one of the convenience
119142
/// methods, such as `get()`, `post()`, etc.
120-
pub struct RequestBuilder<'a, U: IntoUrl, C: NetworkConnector + 'a> {
121-
client: &'a mut Client<C>,
143+
pub struct RequestBuilder<'a, U: IntoUrl> {
144+
client: &'a mut Client,
122145
url: U,
123146
headers: Option<Headers>,
124147
method: Method,
125148
body: Option<Body<'a>>,
126149
}
127150

128-
impl<'a, U: IntoUrl, C: NetworkConnector> RequestBuilder<'a, U, C> {
151+
impl<'a, U: IntoUrl> RequestBuilder<'a, U> {
129152

130153
/// Set a request body to be sent.
131-
pub fn body<B: IntoBody<'a>>(mut self, body: B) -> RequestBuilder<'a, U, C> {
154+
pub fn body<B: IntoBody<'a>>(mut self, body: B) -> RequestBuilder<'a, U> {
132155
self.body = Some(body.into_body());
133156
self
134157
}
135158

136159
/// Add additional headers to the request.
137-
pub fn headers(mut self, headers: Headers) -> RequestBuilder<'a, U, C> {
160+
pub fn headers(mut self, headers: Headers) -> RequestBuilder<'a, U> {
138161
self.headers = Some(headers);
139162
self
140163
}
141164

142165
/// Add an individual new header to the request.
143-
pub fn header<H: Header + HeaderFormat>(mut self, header: H) -> RequestBuilder<'a, U, C> {
166+
pub fn header<H: Header + HeaderFormat>(mut self, header: H) -> RequestBuilder<'a, U> {
144167
{
145168
let mut headers = match self.headers {
146169
Some(ref mut h) => h,

src/client/request.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@ impl Request<Fresh> {
5151
pub fn with_connector<C, S>(method: method::Method, url: Url, connector: &mut C)
5252
-> HttpResult<Request<Fresh>> where
5353
C: NetworkConnector<Stream=S>,
54-
S: NetworkStream + Send {
54+
S: Into<Box<NetworkStream + Send>> {
5555
debug!("{} {}", method, url);
5656
let (host, port) = try!(get_host_and_port(&url));
5757

58-
let stream = try!(connector.connect(&*host, port, &*url.scheme));
59-
// FIXME: Use Type ascription
60-
let stream: Box<NetworkStream + Send> = Box::new(stream);
58+
let stream = try!(connector.connect(&*host, port, &*url.scheme)).into();
6159
let stream = ThroughWriter(BufWriter::new(stream));
6260

6361
let mut headers = Headers::new();

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ mod mimewrapper {
190190

191191
#[allow(unconditional_recursion)]
192192
fn _assert_send<T: Send>() {
193+
_assert_send::<Client>();
193194
_assert_send::<client::Request<net::Fresh>>();
194195
_assert_send::<client::Response>();
195196
}

src/net.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,17 @@ impl<T: NetworkStream + Send + Clone> StreamClone for T {
8383
/// A connector creates a NetworkStream.
8484
pub trait NetworkConnector {
8585
/// Type of Stream to create
86-
type Stream: NetworkStream + Send;
86+
type Stream: Into<Box<NetworkStream + Send>>;
8787
/// Connect to a remote address.
8888
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<Self::Stream>;
8989
}
9090

91+
impl<T: NetworkStream + Send> From<T> for Box<NetworkStream + Send> {
92+
fn from(s: T) -> Box<NetworkStream + Send> {
93+
Box::new(s)
94+
}
95+
}
96+
9197
impl fmt::Debug for Box<NetworkStream + Send> {
9298
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
9399
fmt.pad("Box<NetworkStream>")
@@ -294,13 +300,12 @@ impl NetworkStream for HttpStream {
294300
}
295301

296302
/// A connector that will produce HttpStreams.
297-
#[allow(missing_copy_implementations)]
298-
pub struct HttpConnector<'v>(pub Option<ContextVerifier<'v>>);
303+
pub struct HttpConnector(pub Option<ContextVerifier>);
299304

300305
/// A method that can set verification methods on an SSL context
301-
pub type ContextVerifier<'v> = Box<FnMut(&mut SslContext) -> ()+'v>;
306+
pub type ContextVerifier = Box<FnMut(&mut SslContext) -> () + Send>;
302307

303-
impl<'v> NetworkConnector for HttpConnector<'v> {
308+
impl NetworkConnector for HttpConnector {
304309
type Stream = HttpStream;
305310

306311
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<HttpStream> {

0 commit comments

Comments
 (0)