diff --git a/Cargo.toml b/Cargo.toml index a696a4f..1f5ffba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ bytes = "0.4" encoding_rs = "0.8" futures = "0.1.23" http = "0.1.10" -hyper = "0.12.7" +hyper = "0.12.13" hyper-old-types = { version = "0.11", optional = true, features = ["compat"] } hyper-tls = "0.3" libflate = "0.1.18" diff --git a/src/async_impl/response.rs b/src/async_impl/response.rs index 4485a27..0522f26 100644 --- a/src/async_impl/response.rs +++ b/src/async_impl/response.rs @@ -1,10 +1,12 @@ use std::fmt; use std::mem; use std::marker::PhantomData; +use std::net::SocketAddr; use futures::{Async, Future, Poll, Stream}; use futures::stream::Concat2; use hyper::{HeaderMap, StatusCode, Version}; +use hyper::client::connect::HttpInfo; use serde::de::DeserializeOwned; use serde_json; use url::Url; @@ -23,14 +25,19 @@ pub struct Response { url: Box, body: Decoder, version: Version, + extensions: http::Extensions, } impl Response { - pub(super) fn new(mut res: ::hyper::Response<::hyper::Body>, url: Url, gzip: bool) -> Response { - let status = res.status(); - let version = res.version(); - let mut headers = mem::replace(res.headers_mut(), HeaderMap::new()); - let decoder = Decoder::detect(&mut headers, Body::wrap(res.into_body()), gzip); + pub(super) fn new(res: ::hyper::Response<::hyper::Body>, url: Url, gzip: bool) -> Response { + let (parts, body) = res.into_parts(); + let status = parts.status; + let version = parts.version; + let extensions = parts.extensions; + + let mut headers = parts.headers; + let decoder = Decoder::detect(&mut headers, Body::wrap(body), gzip); + debug!("Response: '{}' for {}", status, url); Response { status, @@ -38,6 +45,7 @@ impl Response { url: Box::new(url), body: decoder, version, + extensions, } } @@ -47,6 +55,14 @@ impl Response { &self.url } + /// Get the remote address used to get this `Response`. + pub fn remote_addr(&self) -> Option { + self + .extensions + .get::() + .map(|info| info.remote_addr()) + } + /// Get the `StatusCode` of this `Response`. #[inline] pub fn status(&self) -> StatusCode { @@ -161,6 +177,7 @@ impl> From> for Response { url: Box::new(url), body: body, version: parts.version, + extensions: parts.extensions, } } } diff --git a/src/response.rs b/src/response.rs index 0454963..5332eab 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,6 +1,7 @@ use std::mem; use std::fmt; use std::io::{self, Read}; +use std::net::SocketAddr; use std::time::Duration; use std::borrow::Cow; @@ -61,6 +62,22 @@ impl Response { self.inner.url() } + /// Get the remote address used to get this `Response`. + /// + /// # Example + /// + /// ```rust + /// # fn run() -> Result<(), Box<::std::error::Error>> { + /// let resp = reqwest::get("http://httpbin.org/redirect/1")?; + /// println!("httpbin.org address: {:?}", resp.remote_addr()); + /// # Ok(()) + /// # } + /// ``` + pub fn remote_addr(&self) -> Option { + self.inner.remote_addr() + + } + /// Get the `StatusCode` of this `Response`. /// /// # Examples diff --git a/tests/client.rs b/tests/client.rs index 7a52cd9..b131732 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -127,6 +127,7 @@ fn test_get() { assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!(res.remote_addr(), Some(server.addr())); let mut buf = [0; 1024]; let n = res.read(&mut buf).unwrap();