Skip to content

Commit

Permalink
finish upgrade hyper and http to version 1
Browse files Browse the repository at this point in the history
  • Loading branch information
lperlaki committed May 28, 2024
1 parent cfc7556 commit 575b701
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 307 deletions.
13 changes: 6 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ base64 = "0.22"
futures = "0.3"
http = "1"
http-body-util = "0.1"
hyper = { version = "1", features = ["http2"] }
hyper-util = "0.1"
hyper = "1"
hyper-util = { version = "0.1.5", features = ["client-legacy", "server-auto", "http1", "http2", "server-graceful"] }
hyper-rustls = { version = "0.27", optional = true, default-features = false, features = ["http2"] }
hyper-tls = { version = "0.6.0", optional = true }
itertools = "0.12"
Expand All @@ -47,18 +47,17 @@ percent-encoding = "2"
rustls = { version = "^0.23", optional = true, features = ["ring"] }
rustls-pemfile = { version = "1.0.1", optional = true }
seahash = "4"
serde = {version = "1.0", features = ["derive"]}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
time = { version = "0.3.7", features = ["local-offset", "parsing", "serde"] }
tokio = { version = "1.0", features = ["fs", "macros", "io-std", "io-util", "time", "sync", "rt"] }
tower-service = "^0.3.1"
tokio = { version = "1.0", features = [ "fs", "macros", "io-std", "io-util", "time", "sync", "rt"] }
url = "2"

[dev-dependencies]
httptest = "0.16"
env_logger = "0.11"
env_logger = "0.10"
tempfile = "3.1"
webbrowser = "1"
webbrowser = "0.8"
hyper-rustls = "0.27"

[workspace]
Expand Down
39 changes: 16 additions & 23 deletions examples/custom_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,22 @@
//!
//! It is also a better use of resources (memory, sockets, etc.)
use std::error::Error as StdError;
use hyper_util::client::legacy::connect::Connect;

use http::Uri;
use hyper_util::client::legacy::connect::Connection;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;

async fn r#use<S>(
client: hyper_util::client::legacy::Client<S, String>,
authenticator: yup_oauth2::authenticator::Authenticator<S>,
async fn r#use<C>(
client: hyper_util::client::legacy::Client<C, String>,
authenticator: yup_oauth2::authenticator::Authenticator<C>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
where
S: Service<Uri> + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>,
C: Connect + Clone + Send + Sync + 'static,
{
let access_token = authenticator.token(&["email"]).await?;
let request = http::Request::get("https://example.com")
.header(
http::header::AUTHORIZATION,
format!("Bearer {}", access_token.token().ok_or("no access token")?),
)
.body(hyper::body::Body::empty())?;
.body(String::new())?;
let response = client.request(request).await?;
drop(response); // Implementing handling of the response is left as an exercise for the reader.
Ok(())
Expand All @@ -41,15 +33,16 @@ async fn main() {
let secret = yup_oauth2::read_service_account_key(google_credentials)
.await
.expect("$GOOGLE_APPLICATION_CREDENTIALS is not a valid service account key");
let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(
hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()
.expect("failed to find native root certificates")
.https_only()
.enable_http1()
.enable_http2()
.build(),
);
let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
.build(
hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()
.expect("failed to find native root certificates")
.https_only()
.enable_http1()
.enable_http2()
.build(),
);
let authenticator =
yup_oauth2::ServiceAccountAuthenticator::with_client(secret, client.clone())
.build()
Expand Down
15 changes: 4 additions & 11 deletions src/access_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
//! access token of the other service by generating a new token.
use crate::error::Error;
use crate::types::TokenInfo;
use http::Uri;
use hyper_util::client::legacy::connect::Connection;
use std::error::Error as StdError;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;
use hyper_util::client::legacy::connect::Connect;

/// the flow for the access token authenticator
pub struct AccessTokenFlow {
Expand All @@ -20,17 +16,14 @@ pub struct AccessTokenFlow {

impl AccessTokenFlow {
/// just return the access token
pub(crate) async fn token<S, T>(
pub(crate) async fn token<C, B, T>(
&self,
_hyper_client: &hyper_util::client::legacy::Client<S, String>,
_hyper_client: &hyper_util::client::legacy::Client<C, B>,
_scopes: &[T],
) -> Result<TokenInfo, Error>
where
T: AsRef<str>,
S: Service<Uri> + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>,
C: Connect + Clone + Send + Sync + 'static,
{
Ok(TokenInfo {
access_token: Some(self.access_token.clone()),
Expand Down
21 changes: 7 additions & 14 deletions src/application_default_credentials.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use crate::error::Error;
use crate::types::TokenInfo;
use http::Uri;
use http_body_util::BodyExt;
use hyper_util::client::legacy::connect::{Connect, Connection};
use std::error::Error as StdError;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;
use hyper_util::client::legacy::connect::Connect;

/// Provide options for the Application Default Credential Flow, mostly used for testing
#[derive(Default, Clone, Debug)]
Expand All @@ -24,26 +20,23 @@ impl ApplicationDefaultCredentialsFlow {
ApplicationDefaultCredentialsFlow { metadata_url }
}

pub(crate) async fn token<S, T>(
pub(crate) async fn token<C, T>(
&self,
hyper_client: &hyper_util::client::legacy::Client<S, String>,
hyper_client: &hyper_util::client::legacy::Client<C, String>,
scopes: &[T],
) -> Result<TokenInfo, Error>
where
T: AsRef<str>,
S: Service<Uri> + Connect + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>
C: Connect + Clone + Send + Sync + 'static,
{
let scope = crate::helper::join(scopes, ",");
let token_uri = format!("{}?scopes={}", self.metadata_url, scope);
let request = hyper::Request::get(token_uri)
let request = http::Request::get(token_uri)
.header("Metadata-Flavor", "Google")
.body(String::new())
.body(String::new()) // why body is needed?
.unwrap();
log::debug!("requesting token from metadata server: {:?}", request);
let (head, body) = hyper_client.request(request).await.map_err(|err| Error::OtherError(err.into()))?.into_parts();
let (head, body) = hyper_client.request(request).await?.into_parts();
let body = body.collect().await?.to_bytes();
log::debug!("received response; head: {:?}, body: {:?}", head, body);
TokenInfo::from_json(&body)
Expand Down
89 changes: 44 additions & 45 deletions src/authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,24 @@ use private::AuthFlow;
use crate::access_token::AccessTokenFlow;

use futures::lock::Mutex;
use http::Uri;
use hyper_util::client::legacy::connect::Connection;
use hyper_util::client::legacy::connect::Connect;
use std::borrow::Cow;
use std::error::Error as StdError;
use std::fmt;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::io::{AsyncRead, AsyncWrite};
use tower_service::Service;

struct InnerAuthenticator<S> {
hyper_client: hyper_util::client::legacy::Client<S, String>,
struct InnerAuthenticator<C> {
hyper_client: hyper_util::client::legacy::Client<C, String>,
storage: Storage,
auth_flow: AuthFlow,
}

/// Authenticator is responsible for fetching tokens, handling refreshing tokens,
/// and optionally persisting tokens to disk.
#[derive(Clone)]
pub struct Authenticator<S> {
inner: Arc<InnerAuthenticator<S>>,
pub struct Authenticator<C> {
inner: Arc<InnerAuthenticator<C>>,
}

struct DisplayScopes<'a, T>(&'a [T]);
Expand All @@ -63,12 +59,9 @@ where
}
}

impl<S> Authenticator<S>
impl<C> Authenticator<C>
where
S: Service<Uri> + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>,
C: Connect + Clone + Send + Sync + 'static,
{
/// Return the current token for the provided scopes.
pub async fn token<'a, T>(&'a self, scopes: &'a [T]) -> Result<AccessToken, Error>
Expand Down Expand Up @@ -544,7 +537,7 @@ impl ServiceAccountImpersonationAuthenticator {
/// ```
/// # #[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
/// # async fn foo() {
/// # let custom_hyper_client = hyper_util::client::legacy::Client::new();
/// # let custom_hyper_client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build_http::<String>();
/// # let app_secret = yup_oauth2::read_application_secret("/tmp/foo").await.unwrap();
/// let authenticator = yup_oauth2::DeviceFlowAuthenticator::builder(app_secret)
/// .hyper_client(custom_hyper_client)
Expand Down Expand Up @@ -604,10 +597,10 @@ impl<C, F> AuthenticatorBuilder<C, F> {
}

/// Use the provided hyper client.
pub fn hyper_client<NewC, B: hyper::body::Body>(
pub fn hyper_client<NewC>(
self,
hyper_client: hyper_util::client::legacy::Client<NewC, B>,
) -> AuthenticatorBuilder<hyper_util::client::legacy::Client<NewC, B>, F> {
hyper_client: hyper_util::client::legacy::Client<NewC, String>,
) -> AuthenticatorBuilder<hyper_util::client::legacy::Client<NewC, String>, F> {
AuthenticatorBuilder {
hyper_client_builder: hyper_client,
storage_type: self.storage_type,
Expand Down Expand Up @@ -874,7 +867,7 @@ impl<C> AuthenticatorBuilder<C, AccessTokenFlow> {
mod private {
use crate::access_token::AccessTokenFlow;
use crate::application_default_credentials::ApplicationDefaultCredentialsFlow;
use crate::authenticator::{AsyncRead, AsyncWrite, Connection, Service, StdError, Uri};
use crate::authenticator::Connect;
use crate::authorized_user::AuthorizedUserFlow;
use crate::device::DeviceFlow;
use crate::error::Error;
Expand Down Expand Up @@ -912,17 +905,14 @@ mod private {
}
}

pub(crate) async fn token<'a, S, T>(
pub(crate) async fn token<'a, C, T>(
&'a self,
hyper_client: &'a hyper_util::client::legacy::Client<S, String>,
hyper_client: &'a hyper_util::client::legacy::Client<C, String>,
scopes: &'a [T],
) -> Result<TokenInfo, Error>
where
T: AsRef<str>,
S: Service<Uri> + hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>,
C: Connect + Clone + Send + Sync + 'static,
{
match self {
AuthFlow::DeviceFlow(device_flow) => device_flow.token(hyper_client, scopes).await,
Expand Down Expand Up @@ -958,14 +948,17 @@ 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: Service<Uri> + Clone + Send + Sync + 'static;
type Connector: Connect + Clone + Send + Sync + 'static;

/// Create a hyper_util::client::legacy::Client
fn build_hyper_client(self) -> Result<hyper_util::client::legacy::Client<Self::Connector, String>, Error>;
/// Create a hyper::Client
fn build_hyper_client(
self,
) -> Result<hyper_util::client::legacy::Client<Self::Connector, String>, Error>;

/// Create a `hyper_util::client::legacy::Client` for tests (HTTPS not required)
#[doc(hidden)]
fn build_test_hyper_client(self) -> hyper_util::client::legacy::Client<Self::Connector, String>;
fn build_test_hyper_client(self)
-> hyper_util::client::legacy::Client<Self::Connector, String>;
}

#[cfg(feature = "hyper-rustls")]
Expand All @@ -984,7 +977,7 @@ pub type DefaultAuthenticator =
)]
/// Default authenticator type
pub type DefaultAuthenticator =
Authenticator<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>;
Authenticator<hyper_tls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>>;

/// The builder value used when the default hyper client should be used.
#[cfg(any(feature = "hyper-rustls", feature = "hyper-tls"))]
Expand All @@ -1001,11 +994,14 @@ pub struct DefaultHyperClient;
)]
impl HyperClientBuilder for DefaultHyperClient {
#[cfg(feature = "hyper-rustls")]
type Connector = hyper_rustls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
type Connector =
hyper_rustls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))]
type Connector = hyper_tls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;

fn build_hyper_client(self) -> Result<hyper_util::client::legacy::Client<Self::Connector, String>, Error> {
fn build_hyper_client(
self,
) -> Result<hyper_util::client::legacy::Client<Self::Connector, String>, Error> {
#[cfg(feature = "hyper-rustls")]
let connector = hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()?
Expand All @@ -1016,12 +1012,16 @@ impl HyperClientBuilder for DefaultHyperClient {
#[cfg(all(not(feature = "hyper-rustls"), feature = "hyper-tls"))]
let connector = hyper_tls::HttpsConnector::new();

Ok(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
.pool_max_idle_per_host(0)
.build::<_, _>(connector))
Ok(
hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
.pool_max_idle_per_host(0)
.build::<_, String>(connector),
)
}

fn build_test_hyper_client(self) -> hyper_util::client::legacy::Client<Self::Connector, String> {
fn build_test_hyper_client(
self,
) -> hyper_util::client::legacy::Client<Self::Connector, String> {
#[cfg(feature = "hyper-rustls")]
let connector = hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()
Expand All @@ -1035,24 +1035,23 @@ impl HyperClientBuilder for DefaultHyperClient {

hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
.pool_max_idle_per_host(0)
.build::<_, _>(connector)
.build::<_, String>(connector)
}
}

impl<S> HyperClientBuilder for hyper_util::client::legacy::Client<S, String>
impl<C> HyperClientBuilder for hyper_util::client::legacy::Client<C, String>
where
S: Service<Uri> + Clone + Send + Sync + 'static,
S::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
S::Future: Send + Unpin + 'static,
S::Error: Into<Box<dyn StdError + Send + Sync>>,
C: Connect + Clone + Send + Sync + 'static,
{
type Connector = S;
type Connector = C;

fn build_hyper_client(self) -> Result<hyper_util::client::legacy::Client<S, String>, Error> {
fn build_hyper_client(self) -> Result<hyper_util::client::legacy::Client<C, String>, Error> {
Ok(self)
}

fn build_test_hyper_client(self) -> hyper_util::client::legacy::Client<Self::Connector, String> {
fn build_test_hyper_client(
self,
) -> hyper_util::client::legacy::Client<Self::Connector, String> {
self
}
}
Expand Down
Loading

0 comments on commit 575b701

Please sign in to comment.