From<http::Response> for Response (#360)
This adds an implementation to convert a `Response` type from the `http` crate to the `async_impl::Response` type. This is the first step to allow us to convert `http::Response` objects to `request::Response` objects This also adds an extension trait for the `http::response::Builder` type. The `http::Response` object does not provide a way to access the "final" url that the response is derived from, so we can't easily provide that in the `From<http::Response>` implementation. For users who are manually constructing `http::Response` objects for use in tests, etc, they can import this extension trait, which adds a `.url()` builder method that will allow them to pass a `Url`, which we then convert to our newtype'd Url and add to the `http::Response`'s `extensions`. Then, when converting from `http::Response` to `async_impl::Response` we can pull that value out of the `extensions` and use it to construct the `async_impl::Response` Closes #333
This commit is contained in:
committed by
Sean McArthur
parent
22fa725f48
commit
4857a5917d
@@ -2,7 +2,7 @@ pub use self::body::{Body, Chunk};
|
||||
pub use self::decoder::{Decoder, ReadableChunks};
|
||||
pub use self::client::{Client, ClientBuilder};
|
||||
pub use self::request::{Request, RequestBuilder};
|
||||
pub use self::response::Response;
|
||||
pub use self::response::{Response, ResponseBuilderExt};
|
||||
|
||||
pub mod body;
|
||||
pub mod client;
|
||||
|
||||
@@ -8,6 +8,7 @@ use hyper::{HeaderMap, StatusCode, Version};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json;
|
||||
use url::Url;
|
||||
use http;
|
||||
|
||||
use super::{decoder, body, Decoder};
|
||||
|
||||
@@ -144,6 +145,25 @@ impl fmt::Debug for Response {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<body::Body>> From<http::Response<T>> for Response {
|
||||
fn from(r: http::Response<T>) -> Response {
|
||||
let (mut parts, body) = r.into_parts();
|
||||
let body = body.into();
|
||||
let body = decoder::detect(&mut parts.headers, body, false);
|
||||
let url = parts.extensions
|
||||
.remove::<ResponseUrl>()
|
||||
.unwrap_or_else(|| ResponseUrl(Url::parse("http://no.url.provided.local").unwrap()));
|
||||
let url = url.0;
|
||||
Response {
|
||||
status: parts.status,
|
||||
headers: parts.headers,
|
||||
url: Box::new(url),
|
||||
body: body,
|
||||
version: parts.version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Json<T> {
|
||||
concat: Concat2<Decoder>,
|
||||
_marker: PhantomData<T>,
|
||||
@@ -166,3 +186,72 @@ impl<T> fmt::Debug for Json<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct ResponseUrl(Url);
|
||||
|
||||
/// Extension trait for http::response::Builder objects
|
||||
///
|
||||
/// Allows the user to add a `Url` to the http::Response
|
||||
pub trait ResponseBuilderExt {
|
||||
/// A builder method for the `http::response::Builder` type that allows the user to add a `Url`
|
||||
/// to the `http::Response`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate url;
|
||||
/// # extern crate http;
|
||||
/// # extern crate reqwest;
|
||||
/// # use std::error::Error;
|
||||
/// use url::Url;
|
||||
/// use http::response::Builder;
|
||||
/// use reqwest::async::ResponseBuilderExt;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// let response = Builder::new()
|
||||
/// .status(200)
|
||||
/// .url(Url::parse("http://example.com")?)
|
||||
/// .body(())?;
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
fn url(&mut self, url: Url) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ResponseBuilderExt for http::response::Builder {
|
||||
fn url(&mut self, url: Url) -> &mut Self {
|
||||
self.extension(ResponseUrl(url))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use url::Url;
|
||||
use http::response::Builder;
|
||||
use super::{Response, ResponseUrl, ResponseBuilderExt};
|
||||
|
||||
#[test]
|
||||
fn test_response_builder_ext() {
|
||||
let url = Url::parse("http://example.com").unwrap();
|
||||
let response = Builder::new()
|
||||
.status(200)
|
||||
.url(url.clone())
|
||||
.body(())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.extensions().get::<ResponseUrl>(), Some(&ResponseUrl(url)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_http_response() {
|
||||
let url = Url::parse("http://example.com").unwrap();
|
||||
let response = Builder::new()
|
||||
.status(200)
|
||||
.url(url.clone())
|
||||
.body("foo")
|
||||
.unwrap();
|
||||
let response = Response::from(response);
|
||||
|
||||
assert_eq!(response.status, 200);
|
||||
assert_eq!(response.url, Box::new(url));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ impl ClientHandle {
|
||||
}
|
||||
};
|
||||
res.map(|res| {
|
||||
response::new(res, self.timeout.0, KeepCoreThreadAlive(self.inner.clone()))
|
||||
response::new(res, self.timeout.0, KeepCoreThreadAlive(Some(self.inner.clone())))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -517,4 +517,10 @@ impl Default for Timeout {
|
||||
|
||||
// pub(crate)
|
||||
|
||||
pub struct KeepCoreThreadAlive(Arc<InnerClientHandle>);
|
||||
pub struct KeepCoreThreadAlive(Option<Arc<InnerClientHandle>>);
|
||||
|
||||
impl KeepCoreThreadAlive {
|
||||
pub(crate) fn empty() -> KeepCoreThreadAlive {
|
||||
KeepCoreThreadAlive(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ pub mod async {
|
||||
Request,
|
||||
RequestBuilder,
|
||||
Response,
|
||||
ResponseBuilderExt,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::borrow::Cow;
|
||||
|
||||
use encoding_rs::{Encoding, UTF_8};
|
||||
use futures::{Async, Poll, Stream};
|
||||
use http;
|
||||
use mime::Mime;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json;
|
||||
@@ -336,3 +337,9 @@ pub fn new(mut res: async_impl::Response, timeout: Option<Duration>, thread: Kee
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<async_impl::body::Body>> From<http::Response<T>> for Response {
|
||||
fn from(r: http::Response<T>) -> Response {
|
||||
let response = async_impl::Response::from(r);
|
||||
new(response, None, KeepCoreThreadAlive::empty())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user