put all TLS functionality behind a feature flag

The "Cargo feature" `default-tls`, which is enabled by default, is
added, with all TLS support relying on it. This allows using reqwest but
disabling the `native-tls` dependency, by disabling this feature.

Closes #225
This commit is contained in:
Sean McArthur
2018-10-29 13:33:04 -07:00
parent 478ef9bf15
commit 97393143a5
8 changed files with 127 additions and 36 deletions

View File

@@ -8,18 +8,15 @@ matrix:
rust: stable rust: stable
- rust: stable - rust: stable
env: FEATURES=""
- rust: beta - rust: beta
env: FEATURES=""
- rust: nightly - rust: nightly
env: FEATURES=""
# Disable default-tls
- rust: stable
env: FEATURES="--no-default-features"
- rust: stable - rust: stable
env: FEATURES="--features hyper-011" env: FEATURES="--features hyper-011"
- rust: beta
env: FEATURES="--features hyper-011"
- rust: nightly
env: FEATURES="--features hyper-011"
# minimum version # minimum version
- rust: 1.26.0 - rust: 1.26.0

View File

@@ -17,12 +17,12 @@ futures = "0.1.23"
http = "0.1.10" http = "0.1.10"
hyper = "0.12.13" hyper = "0.12.13"
hyper-old-types = { version = "0.11", optional = true, features = ["compat"] } hyper-old-types = { version = "0.11", optional = true, features = ["compat"] }
hyper-tls = "0.3" hyper-tls = { version = "0.3", optional = true }
libflate = "0.1.18" libflate = "0.1.18"
log = "0.4" log = "0.4"
mime = "0.3.7" mime = "0.3.7"
mime_guess = "2.0.0-alpha.6" mime_guess = "2.0.0-alpha.6"
native-tls = "0.2" native-tls = { version = "0.2", optional = true }
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_urlencoded = "0.5" serde_urlencoded = "0.5"
@@ -36,8 +36,9 @@ env_logger = "0.5"
serde_derive = "1.0" serde_derive = "1.0"
[features] [features]
default = [] default = ["default-tls"]
hyper-011 = ["hyper-old-types"] hyper-011 = ["hyper-old-types"]
default-tls = ["hyper-tls", "native-tls"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docs_rs_workaround"] rustdoc-args = ["--cfg", "docs_rs_workaround"]

View File

@@ -8,6 +8,7 @@ use hyper::client::ResponseFuture;
use header::{HeaderMap, HeaderValue, LOCATION, USER_AGENT, REFERER, ACCEPT, use header::{HeaderMap, HeaderValue, LOCATION, USER_AGENT, REFERER, ACCEPT,
ACCEPT_ENCODING, RANGE, TRANSFER_ENCODING, CONTENT_TYPE, CONTENT_LENGTH, CONTENT_ENCODING}; ACCEPT_ENCODING, RANGE, TRANSFER_ENCODING, CONTENT_TYPE, CONTENT_LENGTH, CONTENT_ENCODING};
use mime::{self}; use mime::{self};
#[cfg(feature = "default-tls")]
use native_tls::{TlsConnector, TlsConnectorBuilder}; use native_tls::{TlsConnector, TlsConnectorBuilder};
@@ -16,7 +17,9 @@ use super::response::Response;
use connect::Connector; use connect::Connector;
use into_url::to_uri; use into_url::to_uri;
use redirect::{self, RedirectPolicy, remove_sensitive_headers}; use redirect::{self, RedirectPolicy, remove_sensitive_headers};
use {Certificate, Identity, IntoUrl, Method, Proxy, StatusCode, Url}; use {IntoUrl, Method, Proxy, StatusCode, Url};
#[cfg(feature = "default-tls")]
use {Certificate, Identity};
static DEFAULT_USER_AGENT: &'static str = static DEFAULT_USER_AGENT: &'static str =
concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
@@ -41,12 +44,15 @@ pub struct ClientBuilder {
struct Config { struct Config {
gzip: bool, gzip: bool,
headers: HeaderMap, headers: HeaderMap,
#[cfg(feature = "default-tls")]
hostname_verification: bool, hostname_verification: bool,
#[cfg(feature = "default-tls")]
certs_verification: bool, certs_verification: bool,
proxies: Vec<Proxy>, proxies: Vec<Proxy>,
redirect_policy: RedirectPolicy, redirect_policy: RedirectPolicy,
referer: bool, referer: bool,
timeout: Option<Duration>, timeout: Option<Duration>,
#[cfg(feature = "default-tls")]
tls: TlsConnectorBuilder, tls: TlsConnectorBuilder,
dns_threads: usize, dns_threads: usize,
} }
@@ -62,12 +68,15 @@ impl ClientBuilder {
config: Config { config: Config {
gzip: true, gzip: true,
headers: headers, headers: headers,
#[cfg(feature = "default-tls")]
hostname_verification: true, hostname_verification: true,
#[cfg(feature = "default-tls")]
certs_verification: true, certs_verification: true,
proxies: Vec::new(), proxies: Vec::new(),
redirect_policy: RedirectPolicy::default(), redirect_policy: RedirectPolicy::default(),
referer: true, referer: true,
timeout: None, timeout: None,
#[cfg(feature = "default-tls")]
tls: TlsConnector::builder(), tls: TlsConnector::builder(),
dns_threads: 4, dns_threads: 4,
}, },
@@ -80,16 +89,31 @@ impl ClientBuilder {
/// ///
/// This method fails if native TLS backend cannot be initialized. /// This method fails if native TLS backend cannot be initialized.
pub fn build(self) -> ::Result<Client> { pub fn build(self) -> ::Result<Client> {
let mut config = self.config; let config = self.config;
config.tls.danger_accept_invalid_hostnames(!config.hostname_verification);
config.tls.danger_accept_invalid_certs(!config.certs_verification);
let tls = try_!(config.tls.build()); let connector = {
#[cfg(feature = "default-tls")]
{
let mut tls = config.tls;
tls.danger_accept_invalid_hostnames(!config.hostname_verification);
tls.danger_accept_invalid_certs(!config.certs_verification);
let proxies = Arc::new(config.proxies); let tls = try_!(tls.build());
let connector = Connector::new(config.dns_threads, tls, proxies.clone()); let proxies = Arc::new(config.proxies);
Connector::new(config.dns_threads, tls, proxies.clone())
}
#[cfg(not(feature = "default-tls"))]
{
let proxies = Arc::new(config.proxies);
Connector::new(config.dns_threads, proxies.clone())
}
};
let hyper_client = ::hyper::Client::builder() let hyper_client = ::hyper::Client::builder()
.build(connector); .build(connector);
@@ -109,12 +133,14 @@ 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.
#[cfg(feature = "default-tls")]
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder { pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
self.config.tls.add_root_certificate(cert.cert()); self.config.tls.add_root_certificate(cert.cert());
self self
} }
/// Sets the identity to be used for client certificate authentication. /// Sets the identity to be used for client certificate authentication.
#[cfg(feature = "default-tls")]
pub fn identity(mut self, identity: Identity) -> ClientBuilder { pub fn identity(mut self, identity: Identity) -> ClientBuilder {
self.config.tls.identity(identity.pkcs12()); self.config.tls.identity(identity.pkcs12());
self self
@@ -130,6 +156,7 @@ impl ClientBuilder {
/// hostname verification is not used, any valid certificate for any /// hostname verification is not used, any valid certificate for any
/// site will be trusted for use from any other. This introduces a /// site will be trusted for use from any other. This introduces a
/// significant vulnerability to man-in-the-middle attacks. /// significant vulnerability to man-in-the-middle attacks.
#[cfg(feature = "default-tls")]
pub fn danger_accept_invalid_hostnames(mut self, accept_invalid_hostname: bool) -> ClientBuilder { pub fn danger_accept_invalid_hostnames(mut self, accept_invalid_hostname: bool) -> ClientBuilder {
self.config.hostname_verification = !accept_invalid_hostname; self.config.hostname_verification = !accept_invalid_hostname;
self self
@@ -147,6 +174,7 @@ impl ClientBuilder {
/// will be trusted for use. This includes expired certificates. This /// will be trusted for use. This includes expired certificates. This
/// introduces significant vulnerabilities, and should only be used /// introduces significant vulnerabilities, and should only be used
/// as a last resort. /// as a last resort.
#[cfg(feature = "default-tls")]
pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder { pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
self.config.certs_verification = !accept_invalid_certs; self.config.certs_verification = !accept_invalid_certs;
self self

View File

@@ -9,7 +9,9 @@ use futures::sync::{mpsc, oneshot};
use request::{Request, RequestBuilder}; use request::{Request, RequestBuilder};
use response::Response; use response::Response;
use {async_impl, header, Certificate, Identity, Method, IntoUrl, Proxy, RedirectPolicy, wait}; use {async_impl, header, Method, IntoUrl, Proxy, RedirectPolicy, wait};
#[cfg(feature = "default-tls")]
use {Certificate, Identity};
/// A `Client` to make Requests with. /// A `Client` to make Requests with.
/// ///
@@ -106,6 +108,7 @@ impl ClientBuilder {
/// # Errors /// # Errors
/// ///
/// This method fails if adding root certificate was unsuccessful. /// This method fails if adding root certificate was unsuccessful.
#[cfg(feature = "default-tls")]
pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder { pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {
self.with_inner(move |inner| inner.add_root_certificate(cert)) self.with_inner(move |inner| inner.add_root_certificate(cert))
} }
@@ -133,6 +136,7 @@ impl ClientBuilder {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[cfg(feature = "default-tls")]
pub fn identity(self, identity: Identity) -> ClientBuilder { pub fn identity(self, identity: Identity) -> ClientBuilder {
self.with_inner(move |inner| inner.identity(identity)) self.with_inner(move |inner| inner.identity(identity))
} }
@@ -148,6 +152,7 @@ impl ClientBuilder {
/// hostname verification is not used, any valid certificate for any /// hostname verification is not used, any valid certificate for any
/// site will be trusted for use from any other. This introduces a /// site will be trusted for use from any other. This introduces a
/// significant vulnerability to man-in-the-middle attacks. /// significant vulnerability to man-in-the-middle attacks.
#[cfg(feature = "default-tls")]
pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder { pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder {
self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname)) self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname))
} }
@@ -164,6 +169,7 @@ impl ClientBuilder {
/// will be trusted for use. This includes expired certificates. This /// will be trusted for use. This includes expired certificates. This
/// introduces significant vulnerabilities, and should only be used /// introduces significant vulnerabilities, and should only be used
/// as a last resort. /// as a last resort.
#[cfg(feature = "default-tls")]
pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder { pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs)) self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))
} }

View File

@@ -1,34 +1,50 @@
use bytes::{Buf, BufMut, IntoBuf}; use bytes::{Buf, BufMut};
use futures::{Async, Future, Poll}; use futures::{Future, Poll};
use http::uri::Scheme; use http::uri::Scheme;
use hyper::client::{HttpConnector}; use hyper::client::{HttpConnector};
use hyper::client::connect::{Connect, Connected, Destination}; use hyper::client::connect::{Connect, Connected, Destination};
#[cfg(feature = "default-tls")]
use hyper_tls::{HttpsConnector, MaybeHttpsStream}; use hyper_tls::{HttpsConnector, MaybeHttpsStream};
#[cfg(feature = "default-tls")]
use native_tls::TlsConnector; use native_tls::TlsConnector;
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "default-tls")]
use connect_async::{TlsConnectorExt, TlsStream}; use connect_async::{TlsConnectorExt, TlsStream};
use std::io::{self, Cursor, Read, Write}; use std::io::{self, Read, Write};
use std::sync::Arc; use std::sync::Arc;
use Proxy; use Proxy;
pub(crate) struct Connector { pub(crate) struct Connector {
https: HttpsConnector<HttpConnector>, #[cfg(feature = "default-tls")]
http: HttpsConnector<HttpConnector>,
#[cfg(not(feature = "default-tls"))]
http: HttpConnector,
proxies: Arc<Vec<Proxy>>, proxies: Arc<Vec<Proxy>>,
#[cfg(feature = "default-tls")]
tls: TlsConnector, tls: TlsConnector,
} }
impl Connector { impl Connector {
#[cfg(not(feature = "default-tls"))]
pub(crate) fn new(threads: usize, proxies: Arc<Vec<Proxy>>) -> Connector {
let http = HttpConnector::new(threads);
Connector {
http,
proxies,
}
}
#[cfg(feature = "default-tls")]
pub(crate) fn new(threads: usize, tls: TlsConnector, proxies: Arc<Vec<Proxy>>) -> Connector { pub(crate) fn new(threads: usize, tls: TlsConnector, proxies: Arc<Vec<Proxy>>) -> Connector {
let mut http = HttpConnector::new(threads); let mut http = HttpConnector::new(threads);
http.enforce_http(false); http.enforce_http(false);
let https = HttpsConnector::from((http, tls.clone())); let http = HttpsConnector::from((http, tls.clone()));
Connector { Connector {
https: https, http,
proxies: proxies, proxies,
tls: tls, tls,
} }
} }
} }
@@ -55,11 +71,13 @@ impl Connect for Connector {
ndst.set_port(puri.port()); ndst.set_port(puri.port());
#[cfg(feature = "default-tls")]
{
if dst.scheme() == "https" { if dst.scheme() == "https" {
let host = dst.host().to_owned(); let host = dst.host().to_owned();
let port = dst.port().unwrap_or(443); let port = dst.port().unwrap_or(443);
let tls = self.tls.clone(); let tls = self.tls.clone();
return Box::new(self.https.connect(ndst).and_then(move |(conn, connected)| { return Box::new(self.http.connect(ndst).and_then(move |(conn, connected)| {
trace!("tunneling HTTPS over proxy"); trace!("tunneling HTTPS over proxy");
tunnel(conn, host.clone(), port) tunnel(conn, host.clone(), port)
.and_then(move |tunneled| { .and_then(move |tunneled| {
@@ -69,20 +87,27 @@ impl Connect for Connector {
.map(|io| (Conn::Proxied(io), connected.proxy(true))) .map(|io| (Conn::Proxied(io), connected.proxy(true)))
})); }));
} }
return Box::new(self.https.connect(ndst).map(|(io, connected)| (Conn::Normal(io), connected.proxy(true)))); }
return Box::new(self.http.connect(ndst).map(|(io, connected)| (Conn::Normal(io), connected.proxy(true))));
} }
} }
Box::new(self.https.connect(dst).map(|(io, connected)| (Conn::Normal(io), connected))) Box::new(self.http.connect(dst).map(|(io, connected)| (Conn::Normal(io), connected)))
} }
} }
type HttpStream = <HttpConnector as Connect>::Transport; type HttpStream = <HttpConnector as Connect>::Transport;
#[cfg(feature = "default-tls")]
type HttpsStream = MaybeHttpsStream<HttpStream>; type HttpsStream = MaybeHttpsStream<HttpStream>;
pub(crate) type Connecting = Box<Future<Item=(Conn, Connected), Error=io::Error> + Send>; pub(crate) type Connecting = Box<Future<Item=(Conn, Connected), Error=io::Error> + Send>;
pub(crate) enum Conn { pub(crate) enum Conn {
#[cfg(feature = "default-tls")]
Normal(HttpsStream), Normal(HttpsStream),
#[cfg(not(feature = "default-tls"))]
Normal(HttpStream),
#[cfg(feature = "default-tls")]
Proxied(TlsStream<MaybeHttpsStream<HttpStream>>), Proxied(TlsStream<MaybeHttpsStream<HttpStream>>),
} }
@@ -91,6 +116,7 @@ impl Read for Conn {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match *self { match *self {
Conn::Normal(ref mut s) => s.read(buf), Conn::Normal(ref mut s) => s.read(buf),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.read(buf), Conn::Proxied(ref mut s) => s.read(buf),
} }
} }
@@ -101,6 +127,7 @@ impl Write for Conn {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self { match *self {
Conn::Normal(ref mut s) => s.write(buf), Conn::Normal(ref mut s) => s.write(buf),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.write(buf), Conn::Proxied(ref mut s) => s.write(buf),
} }
} }
@@ -109,6 +136,7 @@ impl Write for Conn {
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
match *self { match *self {
Conn::Normal(ref mut s) => s.flush(), Conn::Normal(ref mut s) => s.flush(),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.flush(), Conn::Proxied(ref mut s) => s.flush(),
} }
} }
@@ -118,6 +146,7 @@ impl AsyncRead for Conn {
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
match *self { match *self {
Conn::Normal(ref s) => s.prepare_uninitialized_buffer(buf), Conn::Normal(ref s) => s.prepare_uninitialized_buffer(buf),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref s) => s.prepare_uninitialized_buffer(buf), Conn::Proxied(ref s) => s.prepare_uninitialized_buffer(buf),
} }
} }
@@ -125,6 +154,7 @@ impl AsyncRead for Conn {
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
match *self { match *self {
Conn::Normal(ref mut s) => s.read_buf(buf), Conn::Normal(ref mut s) => s.read_buf(buf),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.read_buf(buf), Conn::Proxied(ref mut s) => s.read_buf(buf),
} }
} }
@@ -134,6 +164,7 @@ impl AsyncWrite for Conn {
fn shutdown(&mut self) -> Poll<(), io::Error> { fn shutdown(&mut self) -> Poll<(), io::Error> {
match *self { match *self {
Conn::Normal(ref mut s) => s.shutdown(), Conn::Normal(ref mut s) => s.shutdown(),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.shutdown(), Conn::Proxied(ref mut s) => s.shutdown(),
} }
} }
@@ -141,11 +172,13 @@ impl AsyncWrite for Conn {
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
match *self { match *self {
Conn::Normal(ref mut s) => s.write_buf(buf), Conn::Normal(ref mut s) => s.write_buf(buf),
#[cfg(feature = "default-tls")]
Conn::Proxied(ref mut s) => s.write_buf(buf), Conn::Proxied(ref mut s) => s.write_buf(buf),
} }
} }
} }
#[cfg(feature = "default-tls")]
fn tunnel<T>(conn: T, host: String, port: u16) -> Tunnel<T> { fn tunnel<T>(conn: T, host: String, port: u16) -> Tunnel<T> {
let buf = format!("\ let buf = format!("\
CONNECT {0}:{1} HTTP/1.1\r\n\ CONNECT {0}:{1} HTTP/1.1\r\n\
@@ -154,23 +187,26 @@ fn tunnel<T>(conn: T, host: String, port: u16) -> Tunnel<T> {
", host, port).into_bytes(); ", host, port).into_bytes();
Tunnel { Tunnel {
buf: buf.into_buf(), buf: io::Cursor::new(buf),
conn: Some(conn), conn: Some(conn),
state: TunnelState::Writing, state: TunnelState::Writing,
} }
} }
#[cfg(feature = "default-tls")]
struct Tunnel<T> { struct Tunnel<T> {
buf: Cursor<Vec<u8>>, buf: io::Cursor<Vec<u8>>,
conn: Option<T>, conn: Option<T>,
state: TunnelState, state: TunnelState,
} }
#[cfg(feature = "default-tls")]
enum TunnelState { enum TunnelState {
Writing, Writing,
Reading Reading
} }
#[cfg(feature = "default-tls")]
impl<T> Future for Tunnel<T> impl<T> Future for Tunnel<T>
where T: AsyncRead + AsyncWrite { where T: AsyncRead + AsyncWrite {
type Item = T; type Item = T;
@@ -194,7 +230,7 @@ where T: AsyncRead + AsyncWrite {
} else if read.len() > 12 { } else if read.len() > 12 {
if read.starts_with(b"HTTP/1.1 200") || read.starts_with(b"HTTP/1.0 200") { if read.starts_with(b"HTTP/1.1 200") || read.starts_with(b"HTTP/1.0 200") {
if read.ends_with(b"\r\n\r\n") { if read.ends_with(b"\r\n\r\n") {
return Ok(Async::Ready(self.conn.take().unwrap())); return Ok(self.conn.take().unwrap().into());
} }
// else read more // else read more
} else { } else {
@@ -206,6 +242,7 @@ where T: AsyncRead + AsyncWrite {
} }
} }
#[cfg(feature = "default-tls")]
#[inline] #[inline]
fn tunnel_eof() -> io::Error { fn tunnel_eof() -> io::Error {
io::Error::new( io::Error::new(
@@ -214,6 +251,7 @@ fn tunnel_eof() -> io::Error {
) )
} }
#[cfg(feature = "default-tls")]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::io::{Read, Write}; use std::io::{Read, Write};

View File

@@ -1,8 +1,7 @@
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use futures::{Poll, Future, Async}; use futures::{Poll, Future, Async};
use native_tls; use native_tls::{self, HandshakeError, Error, TlsConnector};
use native_tls::{HandshakeError, Error, TlsConnector};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
/// A wrapper around an underlying raw stream which implements the TLS or SSL /// A wrapper around an underlying raw stream which implements the TLS or SSL
@@ -128,4 +127,4 @@ impl<S: Read + Write> Future for MidHandshake<S> {
} }
} }
} }
} }

View File

@@ -135,6 +135,7 @@ impl Error {
Kind::Hyper(ref e) => Some(e), Kind::Hyper(ref e) => Some(e),
Kind::Mime(ref e) => Some(e), Kind::Mime(ref e) => Some(e),
Kind::Url(ref e) => Some(e), Kind::Url(ref e) => Some(e),
#[cfg(feature = "default-tls")]
Kind::Tls(ref e) => Some(e), Kind::Tls(ref e) => Some(e),
Kind::Io(ref e) => Some(e), Kind::Io(ref e) => Some(e),
Kind::UrlEncoded(ref e) => Some(e), Kind::UrlEncoded(ref e) => Some(e),
@@ -224,6 +225,7 @@ impl fmt::Display for Error {
Kind::Mime(ref e) => fmt::Display::fmt(e, f), Kind::Mime(ref e) => fmt::Display::fmt(e, f),
Kind::Url(ref e) => fmt::Display::fmt(e, f), Kind::Url(ref e) => fmt::Display::fmt(e, f),
Kind::UrlBadScheme => f.write_str("URL scheme is not allowed"), Kind::UrlBadScheme => f.write_str("URL scheme is not allowed"),
#[cfg(feature = "default-tls")]
Kind::Tls(ref e) => fmt::Display::fmt(e, f), Kind::Tls(ref e) => fmt::Display::fmt(e, f),
Kind::Io(ref e) => fmt::Display::fmt(e, f), Kind::Io(ref e) => fmt::Display::fmt(e, f),
Kind::UrlEncoded(ref e) => fmt::Display::fmt(e, f), Kind::UrlEncoded(ref e) => fmt::Display::fmt(e, f),
@@ -250,6 +252,7 @@ impl StdError for Error {
Kind::Mime(ref e) => e.description(), Kind::Mime(ref e) => e.description(),
Kind::Url(ref e) => e.description(), Kind::Url(ref e) => e.description(),
Kind::UrlBadScheme => "URL scheme is not allowed", Kind::UrlBadScheme => "URL scheme is not allowed",
#[cfg(feature = "default-tls")]
Kind::Tls(ref e) => e.description(), Kind::Tls(ref e) => e.description(),
Kind::Io(ref e) => e.description(), Kind::Io(ref e) => e.description(),
Kind::UrlEncoded(ref e) => e.description(), Kind::UrlEncoded(ref e) => e.description(),
@@ -267,6 +270,7 @@ impl StdError for Error {
Kind::Hyper(ref e) => e.cause(), Kind::Hyper(ref e) => e.cause(),
Kind::Mime(ref e) => e.cause(), Kind::Mime(ref e) => e.cause(),
Kind::Url(ref e) => e.cause(), Kind::Url(ref e) => e.cause(),
#[cfg(feature = "default-tls")]
Kind::Tls(ref e) => e.cause(), Kind::Tls(ref e) => e.cause(),
Kind::Io(ref e) => e.cause(), Kind::Io(ref e) => e.cause(),
Kind::UrlEncoded(ref e) => e.cause(), Kind::UrlEncoded(ref e) => e.cause(),
@@ -287,6 +291,7 @@ pub(crate) enum Kind {
Mime(::mime::FromStrError), Mime(::mime::FromStrError),
Url(::url::ParseError), Url(::url::ParseError),
UrlBadScheme, UrlBadScheme,
#[cfg(feature = "default-tls")]
Tls(::native_tls::Error), Tls(::native_tls::Error),
Io(io::Error), Io(io::Error),
UrlEncoded(::serde_urlencoded::ser::Error), UrlEncoded(::serde_urlencoded::ser::Error),
@@ -347,6 +352,7 @@ impl From<::serde_json::Error> for Kind {
} }
} }
#[cfg(feature = "default-tls")]
impl From<::native_tls::Error> for Kind { impl From<::native_tls::Error> for Kind {
fn from(err: ::native_tls::Error) -> Kind { fn from(err: ::native_tls::Error) -> Kind {
Kind::Tls(err) Kind::Tls(err)

View File

@@ -117,6 +117,16 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! ## Optional Features
//!
//! The following are a list of [Cargo features][cargo-features] that can be
//! enabled or disabled:
//!
//! - **default-tls** *(enabled by default)*: Provides TLS support via the
//! `native-tls` library to connect over HTTPS.
//! - **hyper-011**: Provides support for hyper's old typed headers.
//!
//!
//! [hyper]: http://hyper.rs //! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html //! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html //! [response]: ./struct.Response.html
@@ -124,6 +134,7 @@
//! [builder]: ./struct.RequestBuilder.html //! [builder]: ./struct.RequestBuilder.html
//! [serde]: http://serde.rs //! [serde]: http://serde.rs
//! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14 //! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
extern crate base64; extern crate base64;
extern crate bytes; extern crate bytes;
@@ -134,12 +145,14 @@ extern crate http;
extern crate hyper; extern crate hyper;
#[cfg(feature = "hyper-011")] #[cfg(feature = "hyper-011")]
pub extern crate hyper_old_types as hyper_011; pub extern crate hyper_old_types as hyper_011;
#[cfg(feature = "default-tls")]
extern crate hyper_tls; extern crate hyper_tls;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate libflate; extern crate libflate;
extern crate mime; extern crate mime;
extern crate mime_guess; extern crate mime_guess;
#[cfg(feature = "default-tls")]
extern crate native_tls; extern crate native_tls;
extern crate serde; extern crate serde;
#[cfg(test)] #[cfg(test)]
@@ -148,7 +161,7 @@ extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
extern crate serde_urlencoded; extern crate serde_urlencoded;
extern crate tokio; extern crate tokio;
#[macro_use] #[cfg_attr(feature = "default-tls", macro_use)]
extern crate tokio_io; extern crate tokio_io;
extern crate url; extern crate url;
extern crate uuid; extern crate uuid;
@@ -167,6 +180,7 @@ pub use self::proxy::Proxy;
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy}; pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
pub use self::request::{Request, RequestBuilder}; pub use self::request::{Request, RequestBuilder};
pub use self::response::Response; pub use self::response::Response;
#[cfg(feature = "default-tls")]
pub use self::tls::{Certificate, Identity}; pub use self::tls::{Certificate, Identity};
@@ -176,6 +190,7 @@ mod error;
mod async_impl; mod async_impl;
mod connect; mod connect;
#[cfg(feature = "default-tls")]
mod connect_async; mod connect_async;
mod body; mod body;
mod client; mod client;
@@ -184,6 +199,7 @@ mod proxy;
mod redirect; mod redirect;
mod request; mod request;
mod response; mod response;
#[cfg(feature = "default-tls")]
mod tls; mod tls;
mod wait; mod wait;