diff --git a/Cargo.toml b/Cargo.toml index 419ea1c..50cf909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,16 +12,20 @@ readme = "README.md" license = "MIT" [features] -default = ["hyper-rustls/rustls-native-certs"] +default = ["hyper-rustls/rustls-native-certs", "hyper-rustls/ring"] webpki-roots = ["hyper-rustls/webpki-roots"] [dependencies] async-trait = "0.1" base64 = "0.22" +bytes = "1" chrono = { version = "0.4.31", features = ["serde"] } home = "0.5.5" -hyper = { version = "0.14.2", features = ["client", "runtime", "http2"] } -hyper-rustls = { version = "0.25", default-features = false, features = ["http1", "http2", "ring", "tokio-runtime"] } +http = "1" +http-body-util = "0.1" +hyper = { version = "1", default-features = false, features = ["client", "http1", "http2"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2"] } +hyper-util = { version = "0.1.4", features = ["client-legacy"] } ring = "0.17" rustls = "0.22" rustls-pemfile = "2" diff --git a/src/config_default_credentials.rs b/src/config_default_credentials.rs index 0912d40..796708c 100644 --- a/src/config_default_credentials.rs +++ b/src/config_default_credentials.rs @@ -2,7 +2,8 @@ use std::fs; use std::sync::Arc; use async_trait::async_trait; -use hyper::body::Body; +use bytes::Bytes; +use http_body_util::Full; use hyper::header::CONTENT_TYPE; use hyper::{Method, Request}; use serde::{Deserialize, Serialize}; @@ -57,15 +58,15 @@ impl ConfigDefaultCredentials { .method(Method::POST) .uri(DEFAULT_TOKEN_GCP_URI) .header(CONTENT_TYPE, "application/json") - .body(Body::from( - serde_json::to_string(&RefreshRequest { + .body(Full::from(Bytes::from( + serde_json::to_vec(&RefreshRequest { client_id: &cred.client_id, client_secret: &cred.client_secret, grant_type: "refresh_token", refresh_token: &cred.refresh_token, }) .unwrap(), - )) + ))) .unwrap() }, "ConfigDefaultCredentials", diff --git a/src/custom_service_account.rs b/src/custom_service_account.rs index 00f64ba..ec44e30 100644 --- a/src/custom_service_account.rs +++ b/src/custom_service_account.rs @@ -7,8 +7,9 @@ use std::{env, fmt}; use async_trait::async_trait; use base64::{engine::general_purpose::URL_SAFE, Engine}; +use bytes::Bytes; use chrono::Utc; -use hyper::body::Body; +use http_body_util::Full; use hyper::header::CONTENT_TYPE; use hyper::Request; use serde::{Deserialize, Serialize}; @@ -75,16 +76,20 @@ impl CustomServiceAccount { async fn fetch_token(&self, scopes: &[&str]) -> Result, Error> { let jwt = Claims::new(&self.credentials, scopes, self.subject.as_deref()).to_jwt(&self.signer)?; - let body = form_urlencoded::Serializer::new(String::new()) - .extend_pairs(&[("grant_type", GRANT_TYPE), ("assertion", jwt.as_str())]) - .finish(); + let body = Bytes::from( + form_urlencoded::Serializer::new(String::new()) + .extend_pairs(&[("grant_type", GRANT_TYPE), ("assertion", jwt.as_str())]) + .finish() + .into_bytes(), + ); + let token = self .client .token( &|| { Request::post(&self.credentials.token_uri) .header(CONTENT_TYPE, "application/x-www-form-urlencoded") - .body(Body::from(body.clone())) + .body(Full::from(body.clone())) .unwrap() }, "CustomServiceAccount", diff --git a/src/metadata_service_account.rs b/src/metadata_service_account.rs index 3cdefda..3f244ac 100644 --- a/src/metadata_service_account.rs +++ b/src/metadata_service_account.rs @@ -2,7 +2,8 @@ use std::str; use std::sync::Arc; use async_trait::async_trait; -use hyper::body::Body; +use bytes::Bytes; +use http_body_util::Full; use hyper::{Method, Request}; use tokio::sync::RwLock; use tracing::{debug, instrument, Level}; @@ -85,12 +86,12 @@ impl TokenProvider for MetadataServiceAccount { } } -fn metadata_request(uri: &str) -> Request { +fn metadata_request(uri: &str) -> Request> { Request::builder() .method(Method::GET) .uri(uri) .header("Metadata-Flavor", "Google") - .body(Body::empty()) + .body(Full::from(Bytes::new())) .unwrap() } diff --git a/src/types.rs b/src/types.rs index b84db6f..d0f85fb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,10 +2,14 @@ use std::fmt; use std::sync::Arc; use std::time::Duration; +use bytes::Buf; use chrono::{DateTime, Utc}; -use hyper::body::{Body, Bytes}; -use hyper::{Client, Request}; +use http_body_util::{BodyExt, Full}; +use hyper::body::Bytes; +use hyper::Request; use hyper_rustls::HttpsConnectorBuilder; +use hyper_util::client::legacy::Client; +use hyper_util::rt::TokioExecutor; use ring::rand::SystemRandom; use ring::signature::{RsaKeyPair, RSA_PKCS1_SHA256}; use serde::{Deserialize, Deserializer}; @@ -15,7 +19,10 @@ use crate::Error; #[derive(Clone, Debug)] pub(crate) struct HttpClient { - inner: Client>, + inner: Client< + hyper_rustls::HttpsConnector, + Full, + >, } impl HttpClient { @@ -30,13 +37,14 @@ impl HttpClient { })?; Ok(Self { - inner: Client::builder().build::<_, Body>(https.https_or_http().enable_http2().build()), + inner: Client::builder(TokioExecutor::new()) + .build(https.https_or_http().enable_http2().build()), }) } pub(crate) async fn token( &self, - request: &impl Fn() -> Request, + request: &impl Fn() -> Request>, provider: &'static str, ) -> Result, Error> { let mut retries = 0; @@ -64,7 +72,7 @@ impl HttpClient { pub(crate) async fn request( &self, - req: Request, + req: Request>, provider: &'static str, ) -> Result { debug!(url = ?req.uri(), provider, "requesting token"); @@ -72,13 +80,16 @@ impl HttpClient { .inner .request(req) .await - .map_err(|err| Error::Http("HTTP request failed", err))? + .map_err(|err| Error::Other("HTTP request failed", Box::new(err)))? .into_parts(); - let body = hyper::body::to_bytes(body) + let mut body = body + .collect() .await - .map_err(|err| Error::Http("failed to read HTTP response body", err))?; + .map_err(|err| Error::Http("failed to read HTTP response body", err))? + .aggregate(); + let body = body.copy_to_bytes(body.remaining()); if !parts.status.is_success() { let body = String::from_utf8_lossy(body.as_ref()); warn!(%body, status = ?parts.status, "token request failed");