summaryrefslogtreecommitdiffstats
path: root/vendor/hyper-tls/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/hyper-tls/src')
-rw-r--r--vendor/hyper-tls/src/client.rs183
-rw-r--r--vendor/hyper-tls/src/lib.rs35
-rw-r--r--vendor/hyper-tls/src/stream.rs111
3 files changed, 329 insertions, 0 deletions
diff --git a/vendor/hyper-tls/src/client.rs b/vendor/hyper-tls/src/client.rs
new file mode 100644
index 000000000..3b8339bba
--- /dev/null
+++ b/vendor/hyper-tls/src/client.rs
@@ -0,0 +1,183 @@
+use std::fmt;
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use hyper::{client::connect::HttpConnector, service::Service, Uri};
+use tokio::io::{AsyncRead, AsyncWrite};
+use tokio_native_tls::TlsConnector;
+
+use crate::stream::MaybeHttpsStream;
+
+type BoxError = Box<dyn std::error::Error + Send + Sync>;
+
+/// A Connector for the `https` scheme.
+#[derive(Clone)]
+pub struct HttpsConnector<T> {
+ force_https: bool,
+ http: T,
+ tls: TlsConnector,
+}
+
+impl HttpsConnector<HttpConnector> {
+ /// Construct a new HttpsConnector.
+ ///
+ /// This uses hyper's default `HttpConnector`, and default `TlsConnector`.
+ /// If you wish to use something besides the defaults, use `From::from`.
+ ///
+ /// # Note
+ ///
+ /// By default this connector will use plain HTTP if the URL provded uses
+ /// the HTTP scheme (eg: http://example.com/).
+ ///
+ /// If you would like to force the use of HTTPS then call https_only(true)
+ /// on the returned connector.
+ ///
+ /// # Panics
+ ///
+ /// This will panic if the underlying TLS context could not be created.
+ ///
+ /// To handle that error yourself, you can use the `HttpsConnector::from`
+ /// constructor after trying to make a `TlsConnector`.
+ pub fn new() -> Self {
+ native_tls::TlsConnector::new()
+ .map(|tls| HttpsConnector::new_(tls.into()))
+ .unwrap_or_else(|e| panic!("HttpsConnector::new() failure: {}", e))
+ }
+
+ fn new_(tls: TlsConnector) -> Self {
+ let mut http = HttpConnector::new();
+ http.enforce_http(false);
+ HttpsConnector::from((http, tls))
+ }
+}
+
+impl<T: Default> Default for HttpsConnector<T> {
+ fn default() -> Self {
+ Self::new_with_connector(Default::default())
+ }
+}
+
+impl<T> HttpsConnector<T> {
+ /// Force the use of HTTPS when connecting.
+ ///
+ /// If a URL is not `https` when connecting, an error is returned.
+ pub fn https_only(&mut self, enable: bool) {
+ self.force_https = enable;
+ }
+
+ /// With connector constructor
+ ///
+ pub fn new_with_connector(http: T) -> Self {
+ native_tls::TlsConnector::new()
+ .map(|tls| HttpsConnector::from((http, tls.into())))
+ .unwrap_or_else(|e| {
+ panic!(
+ "HttpsConnector::new_with_connector(<connector>) failure: {}",
+ e
+ )
+ })
+ }
+}
+
+impl<T> From<(T, TlsConnector)> for HttpsConnector<T> {
+ fn from(args: (T, TlsConnector)) -> HttpsConnector<T> {
+ HttpsConnector {
+ force_https: false,
+ http: args.0,
+ tls: args.1,
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for HttpsConnector<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("HttpsConnector")
+ .field("force_https", &self.force_https)
+ .field("http", &self.http)
+ .finish()
+ }
+}
+
+impl<T> Service<Uri> for HttpsConnector<T>
+where
+ T: Service<Uri>,
+ T::Response: AsyncRead + AsyncWrite + Send + Unpin,
+ T::Future: Send + 'static,
+ T::Error: Into<BoxError>,
+{
+ type Response = MaybeHttpsStream<T::Response>;
+ type Error = BoxError;
+ type Future = HttpsConnecting<T::Response>;
+
+ fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+ match self.http.poll_ready(cx) {
+ Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
+ Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ fn call(&mut self, dst: Uri) -> Self::Future {
+ let is_https = dst.scheme_str() == Some("https");
+ // Early abort if HTTPS is forced but can't be used
+ if !is_https && self.force_https {
+ return err(ForceHttpsButUriNotHttps.into());
+ }
+
+ let host = dst
+ .host()
+ .unwrap_or("")
+ .trim_matches(|c| c == '[' || c == ']')
+ .to_owned();
+ let connecting = self.http.call(dst);
+ let tls = self.tls.clone();
+ let fut = async move {
+ let tcp = connecting.await.map_err(Into::into)?;
+ let maybe = if is_https {
+ let tls = tls.connect(&host, tcp).await?;
+ MaybeHttpsStream::Https(tls)
+ } else {
+ MaybeHttpsStream::Http(tcp)
+ };
+ Ok(maybe)
+ };
+ HttpsConnecting(Box::pin(fut))
+ }
+}
+
+fn err<T>(e: BoxError) -> HttpsConnecting<T> {
+ HttpsConnecting(Box::pin(async { Err(e) }))
+}
+
+type BoxedFut<T> = Pin<Box<dyn Future<Output = Result<MaybeHttpsStream<T>, BoxError>> + Send>>;
+
+/// A Future representing work to connect to a URL, and a TLS handshake.
+pub struct HttpsConnecting<T>(BoxedFut<T>);
+
+impl<T: AsyncRead + AsyncWrite + Unpin> Future for HttpsConnecting<T> {
+ type Output = Result<MaybeHttpsStream<T>, BoxError>;
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Pin::new(&mut self.0).poll(cx)
+ }
+}
+
+impl<T> fmt::Debug for HttpsConnecting<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.pad("HttpsConnecting")
+ }
+}
+
+// ===== Custom Errors =====
+
+#[derive(Debug)]
+struct ForceHttpsButUriNotHttps;
+
+impl fmt::Display for ForceHttpsButUriNotHttps {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("https required but URI was not https")
+ }
+}
+
+impl std::error::Error for ForceHttpsButUriNotHttps {}
diff --git a/vendor/hyper-tls/src/lib.rs b/vendor/hyper-tls/src/lib.rs
new file mode 100644
index 000000000..2245ee34c
--- /dev/null
+++ b/vendor/hyper-tls/src/lib.rs
@@ -0,0 +1,35 @@
+//! # hyper-tls
+//!
+//! An HTTPS connector to be used with [hyper][].
+//!
+//! [hyper]: https://hyper.rs
+//!
+//! ## Example
+//!
+//! ```no_run
+//! use hyper_tls::HttpsConnector;
+//! use hyper::Client;
+//!
+//! #[tokio::main(flavor = "current_thread")]
+//! async fn main() -> Result<(), Box<dyn std::error::Error>>{
+//! let https = HttpsConnector::new();
+//! let client = Client::builder().build::<_, hyper::Body>(https);
+//!
+//! let res = client.get("https://hyper.rs".parse()?).await?;
+//! assert_eq!(res.status(), 200);
+//! Ok(())
+//! }
+//! ```
+#![doc(html_root_url = "https://docs.rs/hyper-tls/0.5.0")]
+#![cfg_attr(test, deny(warnings))]
+#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
+
+#[doc(hidden)]
+pub extern crate native_tls;
+
+pub use client::{HttpsConnecting, HttpsConnector};
+pub use stream::{MaybeHttpsStream, TlsStream};
+
+mod client;
+mod stream;
diff --git a/vendor/hyper-tls/src/stream.rs b/vendor/hyper-tls/src/stream.rs
new file mode 100644
index 000000000..487541003
--- /dev/null
+++ b/vendor/hyper-tls/src/stream.rs
@@ -0,0 +1,111 @@
+use std::fmt;
+use std::io;
+use std::io::IoSlice;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use hyper::client::connect::{Connected, Connection};
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+pub use tokio_native_tls::TlsStream;
+
+/// A stream that might be protected with TLS.
+pub enum MaybeHttpsStream<T> {
+ /// A stream over plain text.
+ Http(T),
+ /// A stream protected with TLS.
+ Https(TlsStream<T>),
+}
+
+// ===== impl MaybeHttpsStream =====
+
+impl<T: fmt::Debug> fmt::Debug for MaybeHttpsStream<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ MaybeHttpsStream::Http(s) => f.debug_tuple("Http").field(s).finish(),
+ MaybeHttpsStream::Https(s) => f.debug_tuple("Https").field(s).finish(),
+ }
+ }
+}
+
+impl<T> From<T> for MaybeHttpsStream<T> {
+ fn from(inner: T) -> Self {
+ MaybeHttpsStream::Http(inner)
+ }
+}
+
+impl<T> From<TlsStream<T>> for MaybeHttpsStream<T> {
+ fn from(inner: TlsStream<T>) -> Self {
+ MaybeHttpsStream::Https(inner)
+ }
+}
+
+impl<T: AsyncRead + AsyncWrite + Unpin> AsyncRead for MaybeHttpsStream<T> {
+ #[inline]
+ fn poll_read(
+ self: Pin<&mut Self>,
+ cx: &mut Context,
+ buf: &mut ReadBuf,
+ ) -> Poll<Result<(), io::Error>> {
+ match Pin::get_mut(self) {
+ MaybeHttpsStream::Http(s) => Pin::new(s).poll_read(cx, buf),
+ MaybeHttpsStream::Https(s) => Pin::new(s).poll_read(cx, buf),
+ }
+ }
+}
+
+impl<T: AsyncWrite + AsyncRead + Unpin> AsyncWrite for MaybeHttpsStream<T> {
+ #[inline]
+ fn poll_write(
+ self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ buf: &[u8],
+ ) -> Poll<Result<usize, io::Error>> {
+ match Pin::get_mut(self) {
+ MaybeHttpsStream::Http(s) => Pin::new(s).poll_write(cx, buf),
+ MaybeHttpsStream::Https(s) => Pin::new(s).poll_write(cx, buf),
+ }
+ }
+
+ fn poll_write_vectored(
+ self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ bufs: &[IoSlice<'_>],
+ ) -> Poll<Result<usize, io::Error>> {
+ match Pin::get_mut(self) {
+ MaybeHttpsStream::Http(s) => Pin::new(s).poll_write_vectored(cx, bufs),
+ MaybeHttpsStream::Https(s) => Pin::new(s).poll_write_vectored(cx, bufs),
+ }
+ }
+
+ fn is_write_vectored(&self) -> bool {
+ match self {
+ MaybeHttpsStream::Http(s) => s.is_write_vectored(),
+ MaybeHttpsStream::Https(s) => s.is_write_vectored(),
+ }
+ }
+
+ #[inline]
+ fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
+ match Pin::get_mut(self) {
+ MaybeHttpsStream::Http(s) => Pin::new(s).poll_flush(cx),
+ MaybeHttpsStream::Https(s) => Pin::new(s).poll_flush(cx),
+ }
+ }
+
+ #[inline]
+ fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
+ match Pin::get_mut(self) {
+ MaybeHttpsStream::Http(s) => Pin::new(s).poll_shutdown(cx),
+ MaybeHttpsStream::Https(s) => Pin::new(s).poll_shutdown(cx),
+ }
+ }
+}
+
+impl<T: AsyncRead + AsyncWrite + Connection + Unpin> Connection for MaybeHttpsStream<T> {
+ fn connected(&self) -> Connected {
+ match self {
+ MaybeHttpsStream::Http(s) => s.connected(),
+ MaybeHttpsStream::Https(s) => s.get_ref().get_ref().get_ref().connected(),
+ }
+ }
+}