Integrate helper functions inside corresponding structs
This commit is contained in:
committed by
Sean McArthur
parent
647f59756e
commit
c4bf420021
@@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -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()));
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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::*;
|
||||||
|
|||||||
16
src/tls.rs
16
src/tls.rs
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user