add Response::remote_addr() method

The new `remote_addr` method returns an `Option<SocketAddr>`, which is
`Some` if the underlying transport uses socket addresses.

Closes #373
This commit is contained in:
Sean McArthur
2018-10-26 14:23:21 -07:00
parent c91f37babf
commit 478ef9bf15
4 changed files with 41 additions and 6 deletions

View File

@@ -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"

View File

@@ -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<Url>,
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<SocketAddr> {
self
.extensions
.get::<HttpInfo>()
.map(|info| info.remote_addr())
}
/// Get the `StatusCode` of this `Response`.
#[inline]
pub fn status(&self) -> StatusCode {
@@ -161,6 +177,7 @@ impl<T: Into<Body>> From<http::Response<T>> for Response {
url: Box::new(url),
body: body,
version: parts.version,
extensions: parts.extensions,
}
}
}

View File

@@ -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<SocketAddr> {
self.inner.remote_addr()
}
/// Get the `StatusCode` of this `Response`.
///
/// # Examples

View File

@@ -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();