diff --git a/src/authenticator.rs b/src/authenticator.rs index b2adf6ab..935d5770 100644 --- a/src/authenticator.rs +++ b/src/authenticator.rs @@ -4,7 +4,9 @@ use crate::application_default_credentials::{ }; use crate::authenticator_delegate::{DeviceFlowDelegate, InstalledFlowDelegate}; use crate::authorized_user::{AuthorizedUserFlow, AuthorizedUserSecret}; -use crate::client::{HttpClient, LegacyClient}; +#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] +use crate::client::DefaultHyperClient; +use crate::client::{HttpClient, HyperClientBuilder}; use crate::device::DeviceFlow; use crate::error::Error; use crate::external_account::{ExternalAccountFlow, ExternalAccountSecret}; @@ -17,10 +19,6 @@ use crate::service_account::{self, ServiceAccountFlow, ServiceAccountFlowOpts, S use crate::storage::{self, Storage, TokenStorage}; use crate::types::{AccessToken, ApplicationSecret, TokenInfo}; use private::AuthFlow; -#[cfg(all(feature = "aws-lc-rs", feature = "hyper-rustls", not(feature = "ring")))] -use rustls::crypto::aws_lc_rs::default_provider as default_crypto_provider; -#[cfg(all(feature = "ring", feature = "hyper-rustls"))] -use rustls::crypto::ring::default_provider as default_crypto_provider; use crate::access_token::AccessTokenFlow; @@ -933,18 +931,6 @@ mod private { } } -/// A trait implemented for any hyper_util::client::legacy::Client as well as the DefaultHyperClient. -pub trait HyperClientBuilder { - /// The hyper connector that the resulting hyper client will use. - type Connector: Connect + Clone + Send + Sync + 'static; - - /// Sets duration after which a request times out - fn with_timeout(self, timeout: Duration) -> Self; - - /// Create a hyper::Client - fn build_hyper_client(self) -> Result, Error>; -} - #[cfg(feature = "hyper-rustls")] #[cfg_attr(docsrs, doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))))] /// Default authenticator type @@ -957,111 +943,6 @@ pub type DefaultAuthenticator = pub type DefaultAuthenticator = Authenticator>; -/// The builder value used when the default hyper client should be used. -#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))))] -#[derive(Default)] -pub struct DefaultHyperClient { - timeout: Option, -} - -/// Intended for using an existing hyper client with `yup-oauth2`. Instantiate -/// with [`CustomHyperClient::from`] -pub struct CustomHyperClient -where - C: Connect + Clone + Send + Sync + 'static, -{ - client: HttpClient, - timeout: Option, -} - -impl From> for CustomHyperClient -where - C: Connect + Clone + Send + Sync + 'static, -{ - fn from(client: LegacyClient) -> Self { - Self { - client: HttpClient::new(client, None), - timeout: None, - } - } -} - -impl HyperClientBuilder for CustomHyperClient -where - C: Connect + Clone + Send + Sync + 'static, -{ - type Connector = C; - - fn with_timeout(mut self, timeout: Duration) -> Self { - self.timeout = Some(timeout); - self - } - - fn build_hyper_client(self) -> Result, Error> { - Ok(self.client) - } -} - -#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] -impl DefaultHyperClient { - /// Set the duration after which a request times out - pub fn with_timeout(mut self, timeout: Duration) -> Self { - self.timeout = Some(timeout); - self - } -} - -#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))))] -impl HyperClientBuilder for DefaultHyperClient { - #[cfg(feature = "hyper-rustls")] - type Connector = - hyper_rustls::HttpsConnector; - #[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))] - type Connector = hyper_tls::HttpsConnector; - - fn with_timeout(mut self, timeout: Duration) -> Self { - self.timeout = Some(timeout); - self - } - - fn build_hyper_client(self) -> Result, Error> { - #[cfg(feature = "hyper-rustls")] - let connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_native_roots(default_crypto_provider())? - .https_or_http() - .enable_http1() - .enable_http2() - .build(); - #[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))] - let connector = hyper_tls::HttpsConnector::new(); - - Ok(HttpClient::new( - hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()) - .pool_max_idle_per_host(0) - .build::<_, String>(connector), - self.timeout, - )) - } -} - -impl HyperClientBuilder for HttpClient -where - C: Connect + Clone + Send + Sync + 'static, -{ - type Connector = C; - - fn with_timeout(mut self, timeout: Duration) -> Self { - self.set_timeout(timeout); - self - } - - fn build_hyper_client(self) -> Result, Error> { - Ok(self) - } -} - /// How should the acquired tokens be stored? enum StorageType { /// Store tokens in memory (and always log in again to acquire a new token on startup) diff --git a/src/client.rs b/src/client.rs index 4a4f92d2..2bd5e4bc 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,9 +1,16 @@ +//! Module containing the HTTP client used for sending requests use std::time::Duration; use futures::TryFutureExt; use http::Uri; use hyper_util::client::legacy::{connect::Connect, Error as LegacyHyperError}; use thiserror::Error as ThisError; +#[cfg(all(feature = "aws-lc-rs", feature = "hyper-rustls", not(feature = "ring")))] +use rustls::crypto::aws_lc_rs::default_provider as default_crypto_provider; +#[cfg(all(feature = "ring", feature = "hyper-rustls"))] +use rustls::crypto::ring::default_provider as default_crypto_provider; + +use crate::Error; type HyperResponse = http::Response; pub(crate) type LegacyClient = hyper_util::client::legacy::Client; @@ -19,6 +26,18 @@ pub enum SendError { Hyper(#[source] LegacyHyperError), } +/// A trait implemented for any hyper_util::client::legacy::Client as well as the DefaultHyperClient. +pub trait HyperClientBuilder { + /// The hyper connector that the resulting hyper client will use. + type Connector: Connect + Clone + Send + Sync + 'static; + + /// Sets duration after which a request times out + fn with_timeout(self, timeout: Duration) -> Self; + + /// Create a hyper::Client + fn build_hyper_client(self) -> Result, Error>; +} + /// Client that can be configured that a request will timeout after a specified /// duration. #[derive(Clone)] @@ -34,14 +53,14 @@ impl HttpClient where C: Connect + Clone + Send + Sync + 'static, { - pub(super) fn new(hyper_client: LegacyClient, timeout: Option) -> Self { + pub(crate) fn new(hyper_client: LegacyClient, timeout: Option) -> Self { Self { client: hyper_client, timeout, } } - pub(super) fn set_timeout(&mut self, timeout: Duration) { + pub(crate) fn set_timeout(&mut self, timeout: Duration) { self.timeout = Some(timeout); } @@ -52,6 +71,22 @@ where } } +impl HyperClientBuilder for HttpClient +where + C: Connect + Clone + Send + Sync + 'static, +{ + type Connector = C; + + fn with_timeout(mut self, timeout: Duration) -> Self { + self.set_timeout(timeout); + self + } + + fn build_hyper_client(self) -> Result, Error> { + Ok(self) + } +} + impl SendRequest for HttpClient where C: Connect + Clone + Send + Sync + 'static, @@ -70,6 +105,95 @@ where } } -pub(super) trait SendRequest { +pub(crate) trait SendRequest { async fn request(&self, payload: http::Request) -> Result; } + +/// The builder value used when the default hyper client should be used. +#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))))] +#[derive(Default)] +pub struct DefaultHyperClient { + timeout: Option, +} + +#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] +impl DefaultHyperClient { + /// Set the duration after which a request times out + pub fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + self + } +} + +#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))))] +impl HyperClientBuilder for DefaultHyperClient { + #[cfg(feature = "hyper-rustls")] + type Connector = + hyper_rustls::HttpsConnector; + #[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))] + type Connector = hyper_tls::HttpsConnector; + + fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + self + } + + fn build_hyper_client(self) -> Result, Error> { + #[cfg(feature = "hyper-rustls")] + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_provider_and_native_roots(default_crypto_provider())? + .https_or_http() + .enable_http1() + .enable_http2() + .build(); + #[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))] + let connector = hyper_tls::HttpsConnector::new(); + + Ok(HttpClient::new( + hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()) + .pool_max_idle_per_host(0) + .build::<_, String>(connector), + self.timeout, + )) + } +} + +/// Intended for using an existing hyper client with `yup-oauth2`. Instantiate +/// with [`CustomHyperClient::from`] +pub struct CustomHyperClient +where + C: Connect + Clone + Send + Sync + 'static, +{ + client: HttpClient, + timeout: Option, +} + +impl From> for CustomHyperClient +where + C: Connect + Clone + Send + Sync + 'static, +{ + fn from(client: LegacyClient) -> Self { + Self { + client: HttpClient::new(client, None), + timeout: None, + } + } +} + +impl HyperClientBuilder for CustomHyperClient +where + C: Connect + Clone + Send + Sync + 'static, +{ + type Connector = C; + + fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + self + } + + fn build_hyper_client(self) -> Result, Error> { + Ok(self.client) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1a7d2b78..41ae3550 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,7 +77,7 @@ mod application_default_credentials; pub mod authenticator; pub mod authenticator_delegate; pub mod authorized_user; -mod client; +pub mod client; mod device; pub mod error; pub mod external_account; @@ -107,12 +107,13 @@ pub use crate::authenticator::ServiceAccountAuthenticator; #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] pub use crate::authenticator::AccessTokenAuthenticator; +pub use crate::client::{HttpClient, CustomHyperClient}; #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))] -pub use crate::client::HttpClient; +pub use crate::client::DefaultHyperClient; #[doc(inline)] pub use crate::authenticator::{ - ApplicationDefaultCredentialsAuthenticator, AuthorizedUserAuthenticator, CustomHyperClient, + ApplicationDefaultCredentialsAuthenticator, AuthorizedUserAuthenticator, DeviceFlowAuthenticator, ExternalAccountAuthenticator, InstalledFlowAuthenticator, ServiceAccountImpersonationAuthenticator, }; diff --git a/tests/tests.rs b/tests/tests.rs index 26971c15..3c4d7957 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,11 +1,12 @@ use yup_oauth2::{ - authenticator::{DefaultAuthenticator, DefaultHyperClient, HyperClientBuilder}, + authenticator::DefaultAuthenticator, authenticator_delegate::{DeviceAuthResponse, DeviceFlowDelegate, InstalledFlowDelegate}, + client::HyperClientBuilder, error::SendError, AccessTokenAuthenticator, ApplicationDefaultCredentialsAuthenticator, - ApplicationDefaultCredentialsFlowOpts, ApplicationSecret, DeviceFlowAuthenticator, HttpClient, - InstalledFlowAuthenticator, InstalledFlowReturnMethod, ServiceAccountAuthenticator, - ServiceAccountKey, + ApplicationDefaultCredentialsFlowOpts, ApplicationSecret, DefaultHyperClient, + DeviceFlowAuthenticator, HttpClient, InstalledFlowAuthenticator, InstalledFlowReturnMethod, + ServiceAccountAuthenticator, ServiceAccountKey, }; use std::path::PathBuf;