Skip to content

Commit d18a53b

Browse files
committed
make Client: Send + Sync, RequestBuilder: Send, Response: Send
1 parent 552f471 commit d18a53b

File tree

3 files changed

+66
-17
lines changed

3 files changed

+66
-17
lines changed

src/body.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl Body {
2121
///
2222
/// A `Body` constructed from a set of bytes, like `String` or `Vec<u8>`,
2323
/// are stored differently and can be reused.
24-
pub fn new<R: Read + 'static>(reader: R) -> Body {
24+
pub fn new<R: Read + Send + 'static>(reader: R) -> Body {
2525
Body {
2626
reader: Kind::Reader(Box::new(reader), None),
2727
}
@@ -53,7 +53,7 @@ pub fn read_to_string(mut body: Body) -> ::std::io::Result<String> {
5353
}
5454

5555
enum Kind {
56-
Reader(Box<Read>, Option<u64>),
56+
Reader(Box<Read + Send>, Option<u64>),
5757
Bytes(Vec<u8>),
5858
}
5959

src/client.rs

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use std::fmt;
12
use std::io::{self, Read};
3+
use std::sync::Arc;
24

35
use hyper::client::IntoUrl;
46
use hyper::header::{Headers, ContentType, Location, Referer, UserAgent};
@@ -22,9 +24,8 @@ static DEFAULT_USER_AGENT: &'static str = concat!(env!("CARGO_PKG_NAME"), "/", e
2224
///
2325
/// The `Client` holds a connection pool internally, so it is advised that
2426
/// you create one and reuse it.
25-
#[derive(Debug)]
2627
pub struct Client {
27-
inner: ::hyper::Client,
28+
inner: ClientRef, //::hyper::Client,
2829
}
2930

3031
impl Client {
@@ -33,7 +34,9 @@ impl Client {
3334
let mut client = try!(new_hyper_client());
3435
client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone);
3536
Ok(Client {
36-
inner: client
37+
inner: ClientRef {
38+
hyper: Arc::new(client),
39+
}
3740
})
3841
}
3942

@@ -59,7 +62,7 @@ impl Client {
5962
pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
6063
let url = url.into_url();
6164
RequestBuilder {
62-
client: self,
65+
client: self.inner.clone(),
6366
method: method,
6467
url: url,
6568
_version: HttpVersion::Http11,
@@ -70,6 +73,17 @@ impl Client {
7073
}
7174
}
7275

76+
impl fmt::Debug for Client {
77+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78+
f.pad("Client")
79+
}
80+
}
81+
82+
#[derive(Clone)]
83+
struct ClientRef {
84+
hyper: Arc<::hyper::Client>,
85+
}
86+
7387
fn new_hyper_client() -> ::Result<::hyper::Client> {
7488
use tls::TlsClient;
7589
Ok(::hyper::Client::with_connector(
@@ -82,9 +96,8 @@ fn new_hyper_client() -> ::Result<::hyper::Client> {
8296

8397

8498
/// A builder to construct the properties of a `Request`.
85-
#[derive(Debug)]
86-
pub struct RequestBuilder<'a> {
87-
client: &'a Client,
99+
pub struct RequestBuilder {
100+
client: ClientRef,
88101

89102
method: Method,
90103
url: Result<Url, ::UrlError>,
@@ -94,7 +107,7 @@ pub struct RequestBuilder<'a> {
94107
body: Option<::Result<Body>>,
95108
}
96109

97-
impl<'a> RequestBuilder<'a> {
110+
impl RequestBuilder {
98111
/// Add a `Header` to this Request.
99112
///
100113
/// ```no_run
@@ -105,20 +118,20 @@ impl<'a> RequestBuilder<'a> {
105118
/// .header(UserAgent("foo".to_string()))
106119
/// .send();
107120
/// ```
108-
pub fn header<H: ::header::Header + ::header::HeaderFormat>(mut self, header: H) -> RequestBuilder<'a> {
121+
pub fn header<H: ::header::Header + ::header::HeaderFormat>(mut self, header: H) -> RequestBuilder {
109122
self.headers.set(header);
110123
self
111124
}
112125
/// Add a set of Headers to the existing ones on this Request.
113126
///
114127
/// The headers will be merged in to any already set.
115-
pub fn headers(mut self, headers: ::header::Headers) -> RequestBuilder<'a> {
128+
pub fn headers(mut self, headers: ::header::Headers) -> RequestBuilder {
116129
self.headers.extend(headers.iter());
117130
self
118131
}
119132

120133
/// Set the request body.
121-
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder<'a> {
134+
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
122135
self.body = Some(Ok(body.into()));
123136
self
124137
}
@@ -139,7 +152,7 @@ impl<'a> RequestBuilder<'a> {
139152
/// .form(&params)
140153
/// .send();
141154
/// ```
142-
pub fn form<T: Serialize>(mut self, form: &T) -> RequestBuilder<'a> {
155+
pub fn form<T: Serialize>(mut self, form: &T) -> RequestBuilder {
143156
let body = serde_urlencoded::to_string(form).map_err(::Error::from);
144157
self.headers.set(ContentType::form_url_encoded());
145158
self.body = Some(body.map(|b| b.into()));
@@ -161,7 +174,7 @@ impl<'a> RequestBuilder<'a> {
161174
/// .json(&map)
162175
/// .send();
163176
/// ```
164-
pub fn json<T: Serialize>(mut self, json: &T) -> RequestBuilder<'a> {
177+
pub fn json<T: Serialize>(mut self, json: &T) -> RequestBuilder {
165178
let body = serde_json::to_vec(json).expect("serde to_vec cannot fail");
166179
self.headers.set(ContentType::json());
167180
self.body = Some(Ok(body.into()));
@@ -188,7 +201,7 @@ impl<'a> RequestBuilder<'a> {
188201
loop {
189202
let res = {
190203
debug!("request {:?} \"{}\"", method, url);
191-
let mut req = client.inner.request(method.clone(), url.clone())
204+
let mut req = client.hyper.request(method.clone(), url.clone())
192205
.headers(headers.clone());
193206

194207
if let Some(ref mut b) = body {
@@ -265,40 +278,65 @@ impl<'a> RequestBuilder<'a> {
265278
}
266279
}
267280

281+
impl fmt::Debug for RequestBuilder {
282+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283+
f.debug_struct("RequestBuilder")
284+
.field("method", &self.method)
285+
.field("url", &self.url)
286+
.field("headers", &self.headers)
287+
.finish()
288+
}
289+
}
290+
268291
/// A Response to a submitted `Request`.
269-
#[derive(Debug)]
270292
pub struct Response {
271293
inner: ::hyper::client::Response,
272294
}
273295

274296
impl Response {
275297
/// Get the `StatusCode`.
298+
#[inline]
276299
pub fn status(&self) -> &StatusCode {
277300
&self.inner.status
278301
}
279302

280303
/// Get the `Headers`.
304+
#[inline]
281305
pub fn headers(&self) -> &Headers {
282306
&self.inner.headers
283307
}
284308

285309
/// Get the `HttpVersion`.
310+
#[inline]
286311
pub fn version(&self) -> &HttpVersion {
287312
&self.inner.version
288313
}
289314

290315
/// Try and deserialize the response body as JSON.
316+
#[inline]
291317
pub fn json<T: Deserialize>(&mut self) -> ::Result<T> {
292318
serde_json::from_reader(self).map_err(::Error::from)
293319
}
294320
}
295321

296322
/// Read the body of the Response.
297323
impl Read for Response {
324+
#[inline]
298325
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
299326
self.inner.read(buf)
300327
}
301328
}
329+
330+
impl fmt::Debug for Response {
331+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
332+
f.debug_struct("Response")
333+
.field("status", self.status())
334+
.field("headers", self.headers())
335+
.field("version", self.version())
336+
.finish()
337+
}
338+
}
339+
302340
#[cfg(test)]
303341
mod tests {
304342
use super::*;

src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,14 @@ pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
120120
let client = try!(Client::new());
121121
client.get(url).send()
122122
}
123+
124+
fn _assert_impls() {
125+
fn assert_send<T: Send>() {}
126+
fn assert_sync<T: Sync>() {}
127+
128+
assert_send::<Client>();
129+
assert_sync::<Client>();
130+
131+
assert_send::<RequestBuilder>();
132+
assert_send::<Response>();
133+
}

0 commit comments

Comments
 (0)