Integrate helper functions inside corresponding structs

This commit is contained in:
Yannick Heinrich
2018-10-05 14:02:31 +02:00
committed by Sean McArthur
parent 647f59756e
commit c4bf420021
9 changed files with 111 additions and 116 deletions

View File

@@ -28,6 +28,36 @@ impl Body {
Inner::Hyper(ref body) => body.content_length(),
}
}
#[inline]
pub(crate) fn wrap(body: ::hyper::Body) -> Body {
Body {
inner: Inner::Hyper(body),
}
}
#[inline]
pub(crate) fn empty() -> Body {
Body {
inner: Inner::Hyper(::hyper::Body::empty()),
}
}
#[inline]
pub(crate) fn reusable(chunk: Bytes) -> Body {
Body {
inner: Inner::Reusable(chunk),
}
}
#[inline]
pub(crate) fn into_hyper(self) -> (Option<Bytes>, ::hyper::Body) {
match self.inner {
Inner::Reusable(chunk) => (Some(chunk.clone()), chunk.into()),
Inner::Hyper(b) => (None, b),
}
}
}
impl Stream for Body {
@@ -48,28 +78,28 @@ impl Stream for Body {
impl From<Bytes> for Body {
#[inline]
fn from(bytes: Bytes) -> Body {
reusable(bytes)
Body::reusable(bytes)
}
}
impl From<Vec<u8>> for Body {
#[inline]
fn from(vec: Vec<u8>) -> Body {
reusable(vec.into())
Body::reusable(vec.into())
}
}
impl From<&'static [u8]> for Body {
#[inline]
fn from(s: &'static [u8]) -> Body {
reusable(Bytes::from_static(s))
Body::reusable(Bytes::from_static(s))
}
}
impl From<String> for Body {
#[inline]
fn from(s: String) -> Body {
reusable(s.into())
Body::reusable(s.into())
}
}
@@ -88,6 +118,14 @@ pub struct Chunk {
inner: ::hyper::Chunk,
}
impl Chunk {
#[inline]
pub(crate) fn from_chunk(chunk: Bytes) -> Chunk {
Chunk {
inner: ::hyper::Chunk::from(chunk)
}
}
}
impl Buf for Chunk {
fn bytes(&self) -> &[u8] {
self.inner.bytes()
@@ -145,39 +183,3 @@ impl fmt::Debug for Chunk {
fmt::Debug::fmt(&self.inner, f)
}
}
#[inline]
pub(crate) fn wrap(body: ::hyper::Body) -> Body {
Body {
inner: Inner::Hyper(body),
}
}
#[inline]
pub(crate) fn empty() -> Body {
Body {
inner: Inner::Hyper(::hyper::Body::empty()),
}
}
#[inline]
pub(crate) fn chunk(chunk: Bytes) -> Chunk {
Chunk {
inner: ::hyper::Chunk::from(chunk)
}
}
#[inline]
pub(crate) fn reusable(chunk: Bytes) -> Body {
Body {
inner: Inner::Reusable(chunk),
}
}
#[inline]
pub(crate) fn into_hyper(body: Body) -> (Option<Bytes>, ::hyper::Body) {
match body.inner {
Inner::Reusable(chunk) => (Some(chunk.clone()), chunk.into()),
Inner::Hyper(b) => (None, b),
}
}

View File

@@ -11,7 +11,6 @@ use mime::{self};
use native_tls::{TlsConnector, TlsConnectorBuilder};
use super::body;
use super::request::{Request, RequestBuilder};
use super::response::Response;
use connect::Connector;
@@ -111,15 +110,13 @@ impl ClientBuilder {
/// This can be used to connect to a server that has a self-signed
/// certificate for example.
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
let cert = ::tls::cert(cert);
self.config.tls.add_root_certificate(cert);
self.config.tls.add_root_certificate(cert.cert());
self
}
/// Sets the identity to be used for client certificate authentication.
pub fn identity(mut self, identity: Identity) -> ClientBuilder {
let pkcs12 = ::tls::pkcs12(identity);
self.config.tls.identity(pkcs12);
self.config.tls.identity(identity.pkcs12());
self
}
@@ -345,7 +342,7 @@ impl Client {
let (reusable, body) = match body {
Some(body) => {
let (reusable, body) = body::into_hyper(body);
let (reusable, body) = body.into_hyper();
(Some(reusable), body)
},
None => {
@@ -578,4 +575,3 @@ fn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {
referer.set_fragment(None);
referer.as_str().parse().ok()
}

View File

@@ -32,7 +32,7 @@ use futures::{Async, Future, Poll, Stream};
use hyper::{HeaderMap};
use hyper::header::{CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING, HeaderValue};
use super::{body, Body, Chunk};
use super::{Body, Chunk};
use error;
const INIT_BUFFER_SIZE: usize = 8192;
@@ -79,7 +79,7 @@ impl Decoder {
#[inline]
pub fn empty() -> Decoder {
Decoder {
inner: Inner::PlainText(body::empty())
inner: Inner::PlainText(Body::empty())
}
}
@@ -103,6 +103,48 @@ impl Decoder {
}
}
/// Constructs a Decoder from a hyper request.
///
/// A decoder is just a wrapper around the hyper request that knows
/// how to decode the content body of the request.
///
/// Uses the correct variant by inspecting the Content-Encoding header.
pub(crate) fn detect(headers: &mut HeaderMap, body: Body, check_gzip: bool) -> Decoder {
if !check_gzip {
return Decoder::plain_text(body);
}
let content_encoding_gzip: bool;
let mut is_gzip = {
content_encoding_gzip = headers
.get_all(CONTENT_ENCODING)
.iter()
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"));
content_encoding_gzip ||
headers
.get_all(TRANSFER_ENCODING)
.iter()
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"))
};
if is_gzip {
if let Some(content_length) = headers.get(CONTENT_LENGTH) {
if content_length == "0" {
warn!("GZipped response with content-length of 0");
is_gzip = false;
}
}
}
if content_encoding_gzip {
headers.remove(CONTENT_ENCODING);
headers.remove(CONTENT_LENGTH);
}
if is_gzip {
Decoder::gzip(body)
} else {
Decoder::plain_text(body)
}
}
pub(crate) fn content_length(&self) -> Option<u64> {
match self.inner {
Inner::PlainText(ref body) => body.content_length(),
@@ -145,12 +187,12 @@ impl Future for Pending {
Err(e) => return Err(e)
};
let body = mem::replace(&mut self.body, ReadableChunks::new(body::empty()));
let body = mem::replace(&mut self.body, ReadableChunks::new(Body::empty()));
// libflate does a read_exact([0; 2]), so its impossible to tell
// if the stream was empty, or truly had an UnexpectedEof.
// Therefore, we need to check for EOF first.
match body_state {
StreamState::Eof => Ok(Async::Ready(Inner::PlainText(body::empty()))),
StreamState::Eof => Ok(Async::Ready(Inner::PlainText(Body::empty()))),
StreamState::HasMore => Ok(Async::Ready(Inner::Gzip(Gzip::new(body))))
}
}
@@ -190,7 +232,7 @@ impl Stream for Gzip {
},
Ok(read) => {
unsafe { self.buf.advance_mut(read) };
let chunk = body::chunk(self.buf.split_to(read).freeze());
let chunk = Chunk::from_chunk(self.buf.split_to(read).freeze());
Ok(Async::Ready(Some(chunk)))
},
@@ -386,45 +428,3 @@ impl<S> ReadableChunks<S>
}
}
}
/// Constructs a Decoder from a hyper request.
///
/// A decoder is just a wrapper around the hyper request that knows
/// how to decode the content body of the request.
///
/// Uses the correct variant by inspecting the Content-Encoding header.
pub(crate) fn detect(headers: &mut HeaderMap, body: Body, check_gzip: bool) -> Decoder {
if !check_gzip {
return Decoder::plain_text(body);
}
let content_encoding_gzip: bool;
let mut is_gzip = {
content_encoding_gzip = headers
.get_all(CONTENT_ENCODING)
.iter()
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"));
content_encoding_gzip ||
headers
.get_all(TRANSFER_ENCODING)
.iter()
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"))
};
if is_gzip {
if let Some(content_length) = headers.get(CONTENT_LENGTH) {
if content_length == "0" {
warn!("GZipped response with content-length of 0");
is_gzip = false;
}
}
}
if content_encoding_gzip {
headers.remove(CONTENT_ENCODING);
headers.remove(CONTENT_LENGTH);
}
if is_gzip {
Decoder::gzip(body)
} else {
Decoder::plain_text(body)
}
}

View File

@@ -10,7 +10,8 @@ use serde_json;
use url::Url;
use http;
use super::{decoder, body, Decoder};
use super::Decoder;
use super::body::Body;
/// A Response to a submitted `Request`.
@@ -29,7 +30,7 @@ impl 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);
let decoder = Decoder::detect(&mut headers, Body::wrap(res.into_body()), gzip);
debug!("Response: '{}' for {}", status, url);
Response {
status,
@@ -145,11 +146,11 @@ impl fmt::Debug for Response {
}
}
impl<T: Into<body::Body>> From<http::Response<T>> for Response {
impl<T: Into<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 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()));