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(), 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 { impl Stream for Body {
@@ -48,28 +78,28 @@ impl Stream for Body {
impl From<Bytes> for Body { impl From<Bytes> for Body {
#[inline] #[inline]
fn from(bytes: Bytes) -> Body { fn from(bytes: Bytes) -> Body {
reusable(bytes) Body::reusable(bytes)
} }
} }
impl From<Vec<u8>> for Body { impl From<Vec<u8>> for Body {
#[inline] #[inline]
fn from(vec: Vec<u8>) -> Body { fn from(vec: Vec<u8>) -> Body {
reusable(vec.into()) Body::reusable(vec.into())
} }
} }
impl From<&'static [u8]> for Body { impl From<&'static [u8]> for Body {
#[inline] #[inline]
fn from(s: &'static [u8]) -> Body { fn from(s: &'static [u8]) -> Body {
reusable(Bytes::from_static(s)) Body::reusable(Bytes::from_static(s))
} }
} }
impl From<String> for Body { impl From<String> for Body {
#[inline] #[inline]
fn from(s: String) -> Body { fn from(s: String) -> Body {
reusable(s.into()) Body::reusable(s.into())
} }
} }
@@ -88,6 +118,14 @@ pub struct Chunk {
inner: ::hyper::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 { impl Buf for Chunk {
fn bytes(&self) -> &[u8] { fn bytes(&self) -> &[u8] {
self.inner.bytes() self.inner.bytes()
@@ -145,39 +183,3 @@ impl fmt::Debug for Chunk {
fmt::Debug::fmt(&self.inner, f) 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 native_tls::{TlsConnector, TlsConnectorBuilder};
use super::body;
use super::request::{Request, RequestBuilder}; use super::request::{Request, RequestBuilder};
use super::response::Response; use super::response::Response;
use connect::Connector; use connect::Connector;
@@ -111,15 +110,13 @@ impl ClientBuilder {
/// This can be used to connect to a server that has a self-signed /// This can be used to connect to a server that has a self-signed
/// certificate for example. /// certificate for example.
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder { pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
let cert = ::tls::cert(cert); self.config.tls.add_root_certificate(cert.cert());
self.config.tls.add_root_certificate(cert);
self self
} }
/// Sets the identity to be used for client certificate authentication. /// Sets the identity to be used for client certificate authentication.
pub fn identity(mut self, identity: Identity) -> ClientBuilder { pub fn identity(mut self, identity: Identity) -> ClientBuilder {
let pkcs12 = ::tls::pkcs12(identity); self.config.tls.identity(identity.pkcs12());
self.config.tls.identity(pkcs12);
self self
} }
@@ -345,7 +342,7 @@ impl Client {
let (reusable, body) = match body { let (reusable, body) = match body {
Some(body) => { Some(body) => {
let (reusable, body) = body::into_hyper(body); let (reusable, body) = body.into_hyper();
(Some(reusable), body) (Some(reusable), body)
}, },
None => { None => {
@@ -578,4 +575,3 @@ fn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {
referer.set_fragment(None); referer.set_fragment(None);
referer.as_str().parse().ok() referer.as_str().parse().ok()
} }

View File

@@ -32,7 +32,7 @@ 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, HeaderValue};
use super::{body, Body, Chunk}; use super::{Body, Chunk};
use error; use error;
const INIT_BUFFER_SIZE: usize = 8192; const INIT_BUFFER_SIZE: usize = 8192;
@@ -79,7 +79,7 @@ impl Decoder {
#[inline] #[inline]
pub fn empty() -> Decoder { pub fn empty() -> Decoder {
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> { pub(crate) fn content_length(&self) -> Option<u64> {
match self.inner { match self.inner {
Inner::PlainText(ref body) => body.content_length(), Inner::PlainText(ref body) => body.content_length(),
@@ -145,12 +187,12 @@ impl Future for Pending {
Err(e) => return Err(e) 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 // libflate does a read_exact([0; 2]), so its impossible to tell
// if the stream was empty, or truly had an UnexpectedEof. // if the stream was empty, or truly had an UnexpectedEof.
// Therefore, we need to check for EOF first. // Therefore, we need to check for EOF first.
match body_state { 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)))) StreamState::HasMore => Ok(Async::Ready(Inner::Gzip(Gzip::new(body))))
} }
} }
@@ -190,7 +232,7 @@ impl Stream for Gzip {
}, },
Ok(read) => { Ok(read) => {
unsafe { self.buf.advance_mut(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))) 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 url::Url;
use http; use http;
use super::{decoder, body, Decoder}; use super::Decoder;
use super::body::Body;
/// A Response to a submitted `Request`. /// A Response to a submitted `Request`.
@@ -29,7 +30,7 @@ impl Response {
let status = res.status(); let status = res.status();
let version = res.version(); let version = res.version();
let mut headers = mem::replace(res.headers_mut(), HeaderMap::new()); 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); debug!("Response: '{}' for {}", status, url);
Response { Response {
status, 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 { fn from(r: http::Response<T>) -> Response {
let (mut parts, body) = r.into_parts(); let (mut parts, body) = r.into_parts();
let body = body.into(); 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 let url = parts.extensions
.remove::<ResponseUrl>() .remove::<ResponseUrl>()
.unwrap_or_else(|| ResponseUrl(Url::parse("http://no.url.provided.local").unwrap())); .unwrap_or_else(|| ResponseUrl(Url::parse("http://no.url.provided.local").unwrap()));

View File

@@ -101,11 +101,11 @@ impl Body {
body: (read, len), body: (read, len),
tx: tx, tx: tx,
}; };
(Some(tx), async_impl::body::wrap(rx), len) (Some(tx), async_impl::Body::wrap(rx), len)
}, },
Kind::Bytes(chunk) => { Kind::Bytes(chunk) => {
let len = chunk.len() as u64; let len = chunk.len() as u64;
(None, async_impl::body::reusable(chunk), Some(len)) (None, async_impl::Body::reusable(chunk), Some(len))
} }
} }
} }

View File

@@ -11,7 +11,7 @@ use connect_async::{TlsConnectorExt, TlsStream};
use std::io::{self, Cursor, Read, Write}; use std::io::{self, Cursor, Read, Write};
use std::sync::Arc; use std::sync::Arc;
use {proxy, Proxy}; use Proxy;
pub(crate) struct Connector { pub(crate) struct Connector {
https: HttpsConnector<HttpConnector>, https: HttpsConnector<HttpConnector>,
@@ -40,7 +40,7 @@ impl Connect for Connector {
fn connect(&self, dst: Destination) -> Self::Future { fn connect(&self, dst: Destination) -> Self::Future {
for prox in self.proxies.iter() { for prox in self.proxies.iter() {
if let Some(puri) = proxy::intercept(prox, &dst) { if let Some(puri) = prox.intercept(&dst) {
trace!("proxy({:?}) intercepts {:?}", puri, dst); trace!("proxy({:?}) intercepts {:?}", puri, dst);
let mut ndst = dst.clone(); let mut ndst = dst.clone();
let new_scheme = puri let new_scheme = puri

View File

@@ -280,8 +280,6 @@ impl StdError for Error {
} }
} }
// pub(crate)
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum Kind { pub(crate) enum Kind {
Http(::http::Error), Http(::http::Error),

View File

@@ -128,7 +128,7 @@ impl Proxy {
} }
} }
fn intercept<D: Dst>(&self, uri: &D) -> Option<::hyper::Uri> { pub(crate) fn intercept<D: Dst>(&self, uri: &D) -> Option<::hyper::Uri> {
match self.intercept { match self.intercept {
Intercept::All(ref u) => Some(u.clone()), Intercept::All(ref u) => Some(u.clone()),
Intercept::Http(ref u) => { Intercept::Http(ref u) => {
@@ -203,10 +203,6 @@ impl Dst for Destination {
} }
} }
pub(crate) fn intercept(proxy: &Proxy, uri: &Destination) -> Option<::http::Uri> {
proxy.intercept(uri)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@@ -55,6 +55,11 @@ impl Certificate {
let inner = try_!(native_tls::Certificate::from_pem(der)); let inner = try_!(native_tls::Certificate::from_pem(der));
Ok(Certificate(inner)) Ok(Certificate(inner))
} }
pub(crate) fn cert(self) -> native_tls::Certificate {
self.0
}
} }
impl fmt::Debug for Certificate { impl fmt::Debug for Certificate {
@@ -104,6 +109,10 @@ impl Identity {
let inner = try_!(native_tls::Identity::from_pkcs12(der, password)); let inner = try_!(native_tls::Identity::from_pkcs12(der, password));
Ok(Identity(inner)) Ok(Identity(inner))
} }
pub(crate) fn pkcs12(self) -> native_tls::Identity {
self.0
}
} }
impl fmt::Debug for Identity { impl fmt::Debug for Identity {
@@ -113,10 +122,3 @@ impl fmt::Debug for Identity {
} }
} }
pub(crate) fn cert(cert: Certificate) -> native_tls::Certificate {
cert.0
}
pub(crate) fn pkcs12(identity: Identity) -> native_tls::Identity {
identity.0
}