Add Response::content_length() method
This commit is contained in:
@@ -30,7 +30,7 @@ use bytes::{Buf, BufMut, BytesMut};
|
|||||||
use libflate::non_blocking::gzip;
|
use libflate::non_blocking::gzip;
|
||||||
use futures::{Async, Future, Poll, Stream};
|
use futures::{Async, Future, Poll, Stream};
|
||||||
use hyper::{HeaderMap};
|
use hyper::{HeaderMap};
|
||||||
use hyper::header::{CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING, HeaderValue};
|
use hyper::header::{CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING};
|
||||||
|
|
||||||
use super::{Body, Chunk};
|
use super::{Body, Chunk};
|
||||||
use error;
|
use error;
|
||||||
@@ -118,17 +118,17 @@ impl Decoder {
|
|||||||
content_encoding_gzip = headers
|
content_encoding_gzip = headers
|
||||||
.get_all(CONTENT_ENCODING)
|
.get_all(CONTENT_ENCODING)
|
||||||
.iter()
|
.iter()
|
||||||
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"));
|
.fold(false, |acc, enc| acc || enc == "gzip");
|
||||||
content_encoding_gzip ||
|
content_encoding_gzip ||
|
||||||
headers
|
headers
|
||||||
.get_all(TRANSFER_ENCODING)
|
.get_all(TRANSFER_ENCODING)
|
||||||
.iter()
|
.iter()
|
||||||
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"))
|
.fold(false, |acc, enc| acc || enc == "gzip")
|
||||||
};
|
};
|
||||||
if is_gzip {
|
if is_gzip {
|
||||||
if let Some(content_length) = headers.get(CONTENT_LENGTH) {
|
if let Some(content_length) = headers.get(CONTENT_LENGTH) {
|
||||||
if content_length == "0" {
|
if content_length == "0" {
|
||||||
warn!("GZipped response with content-length of 0");
|
warn!("gzip response with content-length of 0");
|
||||||
is_gzip = false;
|
is_gzip = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use futures::{Async, Future, Poll, Stream};
|
|||||||
use futures::stream::Concat2;
|
use futures::stream::Concat2;
|
||||||
use hyper::{HeaderMap, StatusCode, Version};
|
use hyper::{HeaderMap, StatusCode, Version};
|
||||||
use hyper::client::connect::HttpInfo;
|
use hyper::client::connect::HttpInfo;
|
||||||
|
use hyper::header::{CONTENT_LENGTH};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -49,19 +50,6 @@ impl Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the final `Url` of this `Response`.
|
|
||||||
#[inline]
|
|
||||||
pub fn url(&self) -> &Url {
|
|
||||||
&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`.
|
/// Get the `StatusCode` of this `Response`.
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -81,6 +69,35 @@ impl Response {
|
|||||||
&mut self.headers
|
&mut self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the final `Url` of this `Response`.
|
||||||
|
#[inline]
|
||||||
|
pub fn url(&self) -> &Url {
|
||||||
|
&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 content-length of this response, if known.
|
||||||
|
///
|
||||||
|
/// Reasons it may not be known:
|
||||||
|
///
|
||||||
|
/// - The server didn't send a `content-length` header.
|
||||||
|
/// - The response is gzipped and automatically decoded (thus changing
|
||||||
|
/// the actual decoded length).
|
||||||
|
pub fn content_length(&self) -> Option<u64> {
|
||||||
|
self
|
||||||
|
.headers()
|
||||||
|
.get(CONTENT_LENGTH)
|
||||||
|
.and_then(|ct_len| ct_len.to_str().ok())
|
||||||
|
.and_then(|ct_len| ct_len.parse().ok())
|
||||||
|
}
|
||||||
|
|
||||||
/// Consumes the response, returning the body
|
/// Consumes the response, returning the body
|
||||||
pub fn into_body(self) -> Decoder {
|
pub fn into_body(self) -> Decoder {
|
||||||
self.body
|
self.body
|
||||||
|
|||||||
169
src/response.rs
169
src/response.rs
@@ -46,6 +46,88 @@ impl Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the `StatusCode` of this `Response`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Checking for general status class:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||||
|
/// let resp = reqwest::get("http://httpbin.org/get")?;
|
||||||
|
/// if resp.status().is_success() {
|
||||||
|
/// println!("success!");
|
||||||
|
/// } else if resp.status().is_server_error() {
|
||||||
|
/// println!("server error!");
|
||||||
|
/// } else {
|
||||||
|
/// println!("Something else happened. Status: {:?}", resp.status());
|
||||||
|
/// }
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Checking for specific status codes:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use reqwest::Client;
|
||||||
|
/// use reqwest::StatusCode;
|
||||||
|
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||||
|
/// let client = Client::new();
|
||||||
|
///
|
||||||
|
/// let resp = client.post("http://httpbin.org/post")
|
||||||
|
/// .body("possibly too large")
|
||||||
|
/// .send()?;
|
||||||
|
///
|
||||||
|
/// match resp.status() {
|
||||||
|
/// StatusCode::OK => println!("success!"),
|
||||||
|
/// StatusCode::PAYLOAD_TOO_LARGE => {
|
||||||
|
/// println!("Request payload is too large!");
|
||||||
|
/// }
|
||||||
|
/// s => println!("Received response status: {:?}", s),
|
||||||
|
/// };
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn status(&self) -> StatusCode {
|
||||||
|
self.inner.status()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `Headers` of this `Response`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Saving an etag when caching a file:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use reqwest::Client;
|
||||||
|
/// use reqwest::header::ETAG;
|
||||||
|
///
|
||||||
|
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||||
|
/// let client = Client::new();
|
||||||
|
///
|
||||||
|
/// let mut resp = client.get("http://httpbin.org/cache").send()?;
|
||||||
|
/// if resp.status().is_success() {
|
||||||
|
/// if let Some(etag) = resp.headers().get(ETAG) {
|
||||||
|
/// std::fs::write("etag", etag.as_bytes());
|
||||||
|
/// }
|
||||||
|
/// let mut file = std::fs::File::create("file")?;
|
||||||
|
/// resp.copy_to(&mut file)?;
|
||||||
|
/// }
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
|
self.inner.headers()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the HTTP `Version` of this `Response`.
|
||||||
|
#[inline]
|
||||||
|
pub fn version(&self) -> Version {
|
||||||
|
self.inner.version()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the final `Url` of this `Response`.
|
/// Get the final `Url` of this `Response`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@@ -75,90 +157,17 @@ impl Response {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn remote_addr(&self) -> Option<SocketAddr> {
|
pub fn remote_addr(&self) -> Option<SocketAddr> {
|
||||||
self.inner.remote_addr()
|
self.inner.remote_addr()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `StatusCode` of this `Response`.
|
/// Get the content-length of the response, if it is known.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// Reasons it may not be known:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// - The server didn't send a `content-length` header.
|
||||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
/// - The response is gzipped and automatically decoded (thus changing
|
||||||
/// let resp = reqwest::get("http://httpbin.org/get")?;
|
/// the actual decoded length).
|
||||||
/// if resp.status().is_success() {
|
pub fn content_length(&self) -> Option<u64> {
|
||||||
/// println!("success!");
|
self.inner.content_length()
|
||||||
/// } else if resp.status().is_server_error() {
|
|
||||||
/// println!("server error!");
|
|
||||||
/// } else {
|
|
||||||
/// println!("Something else happened. Status: {:?}", resp.status());
|
|
||||||
/// }
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use reqwest::Client;
|
|
||||||
/// use reqwest::StatusCode;
|
|
||||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
|
||||||
/// let client = Client::new();
|
|
||||||
/// let resp = client.post("http://httpbin.org/post")
|
|
||||||
/// .body("possibly too large")
|
|
||||||
/// .send()?;
|
|
||||||
/// match resp.status() {
|
|
||||||
/// StatusCode::OK => println!("success!"),
|
|
||||||
/// StatusCode::PAYLOAD_TOO_LARGE => {
|
|
||||||
/// println!("Request payload is too large!");
|
|
||||||
/// }
|
|
||||||
/// s => println!("Received response status: {:?}", s),
|
|
||||||
/// };
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
pub fn status(&self) -> StatusCode {
|
|
||||||
self.inner.status()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the `Headers` of this `Response`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// Checking the `Content-Length` header before reading the response body.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use std::io::{Read, Write};
|
|
||||||
/// # use reqwest::Client;
|
|
||||||
/// # use reqwest::header::CONTENT_LENGTH;
|
|
||||||
/// #
|
|
||||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
|
||||||
/// let client = Client::new();
|
|
||||||
/// let mut resp = client.head("http://httpbin.org/bytes/3000").send()?;
|
|
||||||
/// if resp.status().is_success() {
|
|
||||||
/// let len = resp.headers().get(CONTENT_LENGTH)
|
|
||||||
/// .and_then(|ct_len| ct_len.to_str().ok())
|
|
||||||
/// .and_then(|ct_len| ct_len.parse().ok())
|
|
||||||
/// .unwrap_or(0);
|
|
||||||
/// // limit 1mb response
|
|
||||||
/// if len <= 1_000_000 {
|
|
||||||
/// let mut buf = Vec::with_capacity(len as usize);
|
|
||||||
/// let mut resp = reqwest::get("http://httpbin.org/bytes/3000")?;
|
|
||||||
/// if resp.status().is_success() {
|
|
||||||
/// ::std::io::copy(&mut resp, &mut buf)?;
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
pub fn headers(&self) -> &HeaderMap {
|
|
||||||
self.inner.headers()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the HTTP `Version` of this `Response`.
|
|
||||||
#[inline]
|
|
||||||
pub fn version(&self) -> Version {
|
|
||||||
self.inner.version()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try and deserialize the response body as JSON using `serde`.
|
/// Try and deserialize the response body as JSON using `serde`.
|
||||||
|
|||||||
Reference in New Issue
Block a user