make Client: Send + Sync, RequestBuilder: Send, Response: Send
This commit is contained in:
@@ -21,7 +21,7 @@ impl Body {
|
|||||||
///
|
///
|
||||||
/// A `Body` constructed from a set of bytes, like `String` or `Vec<u8>`,
|
/// A `Body` constructed from a set of bytes, like `String` or `Vec<u8>`,
|
||||||
/// are stored differently and can be reused.
|
/// are stored differently and can be reused.
|
||||||
pub fn new<R: Read + 'static>(reader: R) -> Body {
|
pub fn new<R: Read + Send + 'static>(reader: R) -> Body {
|
||||||
Body {
|
Body {
|
||||||
reader: Kind::Reader(Box::new(reader), None),
|
reader: Kind::Reader(Box::new(reader), None),
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ pub fn read_to_string(mut body: Body) -> ::std::io::Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum Kind {
|
enum Kind {
|
||||||
Reader(Box<Read>, Option<u64>),
|
Reader(Box<Read + Send>, Option<u64>),
|
||||||
Bytes(Vec<u8>),
|
Bytes(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
use std::fmt;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hyper::client::IntoUrl;
|
use hyper::client::IntoUrl;
|
||||||
use hyper::header::{Headers, ContentType, Location, Referer, UserAgent};
|
use hyper::header::{Headers, ContentType, Location, Referer, UserAgent};
|
||||||
@@ -22,9 +24,8 @@ static DEFAULT_USER_AGENT: &'static str = concat!(env!("CARGO_PKG_NAME"), "/", e
|
|||||||
///
|
///
|
||||||
/// The `Client` holds a connection pool internally, so it is advised that
|
/// The `Client` holds a connection pool internally, so it is advised that
|
||||||
/// you create one and reuse it.
|
/// you create one and reuse it.
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
inner: ::hyper::Client,
|
inner: ClientRef, //::hyper::Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@@ -33,7 +34,9 @@ impl Client {
|
|||||||
let mut client = try!(new_hyper_client());
|
let mut client = try!(new_hyper_client());
|
||||||
client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone);
|
client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone);
|
||||||
Ok(Client {
|
Ok(Client {
|
||||||
inner: client
|
inner: ClientRef {
|
||||||
|
hyper: Arc::new(client),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ impl Client {
|
|||||||
pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
|
pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
|
||||||
let url = url.into_url();
|
let url = url.into_url();
|
||||||
RequestBuilder {
|
RequestBuilder {
|
||||||
client: self,
|
client: self.inner.clone(),
|
||||||
method: method,
|
method: method,
|
||||||
url: url,
|
url: url,
|
||||||
_version: HttpVersion::Http11,
|
_version: HttpVersion::Http11,
|
||||||
@@ -70,6 +73,17 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Client {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.pad("Client")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ClientRef {
|
||||||
|
hyper: Arc<::hyper::Client>,
|
||||||
|
}
|
||||||
|
|
||||||
fn new_hyper_client() -> ::Result<::hyper::Client> {
|
fn new_hyper_client() -> ::Result<::hyper::Client> {
|
||||||
use tls::TlsClient;
|
use tls::TlsClient;
|
||||||
Ok(::hyper::Client::with_connector(
|
Ok(::hyper::Client::with_connector(
|
||||||
@@ -82,9 +96,8 @@ fn new_hyper_client() -> ::Result<::hyper::Client> {
|
|||||||
|
|
||||||
|
|
||||||
/// A builder to construct the properties of a `Request`.
|
/// A builder to construct the properties of a `Request`.
|
||||||
#[derive(Debug)]
|
pub struct RequestBuilder {
|
||||||
pub struct RequestBuilder<'a> {
|
client: ClientRef,
|
||||||
client: &'a Client,
|
|
||||||
|
|
||||||
method: Method,
|
method: Method,
|
||||||
url: Result<Url, ::UrlError>,
|
url: Result<Url, ::UrlError>,
|
||||||
@@ -94,7 +107,7 @@ pub struct RequestBuilder<'a> {
|
|||||||
body: Option<::Result<Body>>,
|
body: Option<::Result<Body>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RequestBuilder<'a> {
|
impl RequestBuilder {
|
||||||
/// Add a `Header` to this Request.
|
/// Add a `Header` to this Request.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@@ -105,20 +118,20 @@ impl<'a> RequestBuilder<'a> {
|
|||||||
/// .header(UserAgent("foo".to_string()))
|
/// .header(UserAgent("foo".to_string()))
|
||||||
/// .send();
|
/// .send();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn header<H: ::header::Header + ::header::HeaderFormat>(mut self, header: H) -> RequestBuilder<'a> {
|
pub fn header<H: ::header::Header + ::header::HeaderFormat>(mut self, header: H) -> RequestBuilder {
|
||||||
self.headers.set(header);
|
self.headers.set(header);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Add a set of Headers to the existing ones on this Request.
|
/// Add a set of Headers to the existing ones on this Request.
|
||||||
///
|
///
|
||||||
/// The headers will be merged in to any already set.
|
/// The headers will be merged in to any already set.
|
||||||
pub fn headers(mut self, headers: ::header::Headers) -> RequestBuilder<'a> {
|
pub fn headers(mut self, headers: ::header::Headers) -> RequestBuilder {
|
||||||
self.headers.extend(headers.iter());
|
self.headers.extend(headers.iter());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the request body.
|
/// Set the request body.
|
||||||
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder<'a> {
|
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
|
||||||
self.body = Some(Ok(body.into()));
|
self.body = Some(Ok(body.into()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -139,7 +152,7 @@ impl<'a> RequestBuilder<'a> {
|
|||||||
/// .form(¶ms)
|
/// .form(¶ms)
|
||||||
/// .send();
|
/// .send();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn form<T: Serialize>(mut self, form: &T) -> RequestBuilder<'a> {
|
pub fn form<T: Serialize>(mut self, form: &T) -> RequestBuilder {
|
||||||
let body = serde_urlencoded::to_string(form).map_err(::Error::from);
|
let body = serde_urlencoded::to_string(form).map_err(::Error::from);
|
||||||
self.headers.set(ContentType::form_url_encoded());
|
self.headers.set(ContentType::form_url_encoded());
|
||||||
self.body = Some(body.map(|b| b.into()));
|
self.body = Some(body.map(|b| b.into()));
|
||||||
@@ -161,7 +174,7 @@ impl<'a> RequestBuilder<'a> {
|
|||||||
/// .json(&map)
|
/// .json(&map)
|
||||||
/// .send();
|
/// .send();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn json<T: Serialize>(mut self, json: &T) -> RequestBuilder<'a> {
|
pub fn json<T: Serialize>(mut self, json: &T) -> RequestBuilder {
|
||||||
let body = serde_json::to_vec(json).expect("serde to_vec cannot fail");
|
let body = serde_json::to_vec(json).expect("serde to_vec cannot fail");
|
||||||
self.headers.set(ContentType::json());
|
self.headers.set(ContentType::json());
|
||||||
self.body = Some(Ok(body.into()));
|
self.body = Some(Ok(body.into()));
|
||||||
@@ -188,7 +201,7 @@ impl<'a> RequestBuilder<'a> {
|
|||||||
loop {
|
loop {
|
||||||
let res = {
|
let res = {
|
||||||
debug!("request {:?} \"{}\"", method, url);
|
debug!("request {:?} \"{}\"", method, url);
|
||||||
let mut req = client.inner.request(method.clone(), url.clone())
|
let mut req = client.hyper.request(method.clone(), url.clone())
|
||||||
.headers(headers.clone());
|
.headers(headers.clone());
|
||||||
|
|
||||||
if let Some(ref mut b) = body {
|
if let Some(ref mut b) = body {
|
||||||
@@ -265,29 +278,42 @@ impl<'a> RequestBuilder<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for RequestBuilder {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("RequestBuilder")
|
||||||
|
.field("method", &self.method)
|
||||||
|
.field("url", &self.url)
|
||||||
|
.field("headers", &self.headers)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A Response to a submitted `Request`.
|
/// A Response to a submitted `Request`.
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
inner: ::hyper::client::Response,
|
inner: ::hyper::client::Response,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
/// Get the `StatusCode`.
|
/// Get the `StatusCode`.
|
||||||
|
#[inline]
|
||||||
pub fn status(&self) -> &StatusCode {
|
pub fn status(&self) -> &StatusCode {
|
||||||
&self.inner.status
|
&self.inner.status
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `Headers`.
|
/// Get the `Headers`.
|
||||||
|
#[inline]
|
||||||
pub fn headers(&self) -> &Headers {
|
pub fn headers(&self) -> &Headers {
|
||||||
&self.inner.headers
|
&self.inner.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `HttpVersion`.
|
/// Get the `HttpVersion`.
|
||||||
|
#[inline]
|
||||||
pub fn version(&self) -> &HttpVersion {
|
pub fn version(&self) -> &HttpVersion {
|
||||||
&self.inner.version
|
&self.inner.version
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try and deserialize the response body as JSON.
|
/// Try and deserialize the response body as JSON.
|
||||||
|
#[inline]
|
||||||
pub fn json<T: Deserialize>(&mut self) -> ::Result<T> {
|
pub fn json<T: Deserialize>(&mut self) -> ::Result<T> {
|
||||||
serde_json::from_reader(self).map_err(::Error::from)
|
serde_json::from_reader(self).map_err(::Error::from)
|
||||||
}
|
}
|
||||||
@@ -295,10 +321,22 @@ impl Response {
|
|||||||
|
|
||||||
/// Read the body of the Response.
|
/// Read the body of the Response.
|
||||||
impl Read for Response {
|
impl Read for Response {
|
||||||
|
#[inline]
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
self.inner.read(buf)
|
self.inner.read(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Response {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("Response")
|
||||||
|
.field("status", self.status())
|
||||||
|
.field("headers", self.headers())
|
||||||
|
.field("version", self.version())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
11
src/lib.rs
11
src/lib.rs
@@ -120,3 +120,14 @@ pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
|
|||||||
let client = try!(Client::new());
|
let client = try!(Client::new());
|
||||||
client.get(url).send()
|
client.get(url).send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn _assert_impls() {
|
||||||
|
fn assert_send<T: Send>() {}
|
||||||
|
fn assert_sync<T: Sync>() {}
|
||||||
|
|
||||||
|
assert_send::<Client>();
|
||||||
|
assert_sync::<Client>();
|
||||||
|
|
||||||
|
assert_send::<RequestBuilder>();
|
||||||
|
assert_send::<Response>();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user