diff --git a/Cargo.lock b/Cargo.lock index 34979ed4..2543501a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,9 +3595,7 @@ dependencies = [ "futures-util", "headers", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.4.0", - "hyper-rustls", + "http-body-util", "language-tags", "mas-http", "mas-iana", @@ -3607,8 +3605,6 @@ dependencies = [ "oauth2-types", "rand", "rand_chacha", - "rustls 0.23.10", - "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", @@ -3616,7 +3612,6 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http 0.4.4", "tracing", "url", "wiremock", @@ -6423,14 +6418,12 @@ dependencies = [ "http-body 0.4.6", "http-range-header", "httpdate", - "iri-string", "mime", "mime_guess", "percent-encoding", "pin-project-lite", "tokio", "tokio-util", - "tower", "tower-layer", "tower-service", "tracing", diff --git a/crates/http/src/layers/client.rs b/crates/http/src/layers/client.rs index a3f51eb1..bd055fb8 100644 --- a/crates/http/src/layers/client.rs +++ b/crates/http/src/layers/client.rs @@ -16,7 +16,7 @@ use std::time::Duration; use headers::{ContentLength, HeaderMapExt, Host, UserAgent}; use http::{header::USER_AGENT, HeaderValue, Request, Response}; -use hyper::client::connect::HttpInfo; +use hyper_util::client::legacy::connect::HttpInfo; use mas_tower::{ DurationRecorderLayer, DurationRecorderService, EnrichSpan, InFlightCounterLayer, InFlightCounterService, MakeSpan, MetricsAttributes, TraceContextLayer, TraceContextService, diff --git a/crates/oidc-client/Cargo.toml b/crates/oidc-client/Cargo.toml index cdd4a1b3..6332b04d 100644 --- a/crates/oidc-client/Cargo.toml +++ b/crates/oidc-client/Cargo.toml @@ -12,16 +12,7 @@ repository.workspace = true workspace = true [features] -default = ["hyper", "keystore"] -hyper = [ - "dep:http-body", - "dep:hyper", - "dep:hyper-rustls", - "dep:rustls", - "dep:rustls-platform-verifier", - "dep:tower-http", - "tower/limit", -] +default = ["keystore"] keystore = ["dep:mas-keystore"] [dependencies] @@ -50,18 +41,6 @@ mas-jose.workspace = true mas-keystore = { workspace = true, optional = true } oauth2-types.workspace = true -# Default http service -http-body = { workspace = true, optional = true } -hyper = { workspace = true, optional = true } -hyper-rustls = { workspace = true, optional = true } -rustls = { workspace = true, optional = true } -rustls-platform-verifier = { workspace = true, optional = true } - -[dependencies.tower-http] -version = "0.4.4" -features = ["follow-redirect", "set-header", "timeout", "map-request-body", "util"] -optional = true - [dev-dependencies] assert_matches = "1.5.0" bitflags = "2.6.0" @@ -69,3 +48,6 @@ mas-keystore.workspace = true rand_chacha = "0.3.1" tokio.workspace = true wiremock = "0.6.0" +http-body-util.workspace = true + +mas-http = { workspace = true, features = ["client"] } diff --git a/crates/oidc-client/src/http_service/mod.rs b/crates/oidc-client/src/http_service.rs similarity index 94% rename from crates/oidc-client/src/http_service/mod.rs rename to crates/oidc-client/src/http_service.rs index 4051f5b5..658b487b 100644 --- a/crates/oidc-client/src/http_service/mod.rs +++ b/crates/oidc-client/src/http_service.rs @@ -15,7 +15,4 @@ //! Reexports of traits to implement to provide a custom HTTP service for //! `Client`. -#[cfg(feature = "hyper")] -pub mod hyper; - pub use mas_http::{BoxCloneSyncService, HttpService}; diff --git a/crates/oidc-client/src/http_service/hyper.rs b/crates/oidc-client/src/http_service/hyper.rs deleted file mode 100644 index ee9f0ad3..00000000 --- a/crates/oidc-client/src/http_service/hyper.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2022 Kévin Commaille. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! A [`HttpService`] that uses [hyper] as a backend. -//! -//! [hyper]: https://crates.io/crates/hyper - -use std::time::Duration; - -use http::{header::USER_AGENT, HeaderValue}; -use http_body::Full; -use hyper::client::{connect::dns::GaiResolver, HttpConnector}; -use hyper_rustls::HttpsConnectorBuilder; -use mas_http::BodyToBytesResponseLayer; -use tower::{BoxError, ServiceBuilder}; -use tower_http::{timeout::TimeoutLayer, ServiceBuilderExt}; - -use super::HttpService; - -static MAS_USER_AGENT: HeaderValue = HeaderValue::from_static("mas-oidc-client/0.0.1"); - -/// Constructs a [`HttpService`] using [hyper] as a backend. -/// -/// # Panics -/// -/// If the native TLS root certificates fail to load -/// -/// [hyper]: https://crates.io/crates/hyper -#[must_use] -pub fn hyper_service() -> HttpService { - let resolver = ServiceBuilder::new().service(GaiResolver::new()); - - let mut http = HttpConnector::new_with_resolver(resolver); - http.enforce_http(false); - - let tls_config = rustls_platform_verifier::tls_config(); - - let https = HttpsConnectorBuilder::new() - .with_tls_config(tls_config) - .https_or_http() - .enable_http1() - .enable_http2() - .wrap_connector(http); - - let client = hyper::Client::builder().build(https); - - let client = ServiceBuilder::new() - .map_err(BoxError::from) - .map_request_body(Full::new) - .layer(BodyToBytesResponseLayer) - .override_request_header(USER_AGENT, MAS_USER_AGENT.clone()) - .concurrency_limit(10) - .follow_redirects() - .layer(TimeoutLayer::new(Duration::from_secs(10))) - .service(client); - - HttpService::new(client) -} diff --git a/crates/oidc-client/tests/it/main.rs b/crates/oidc-client/tests/it/main.rs index 6edf90a7..e818ac5b 100644 --- a/crates/oidc-client/tests/it/main.rs +++ b/crates/oidc-client/tests/it/main.rs @@ -15,6 +15,8 @@ use std::collections::HashMap; use chrono::{DateTime, Duration, Utc}; +use http_body_util::Full; +use mas_http::{BodyToBytesResponseLayer, BoxCloneSyncService}; use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod}; use mas_jose::{ claims::{self, hash_token}, @@ -24,7 +26,7 @@ use mas_jose::{ }; use mas_keystore::{JsonWebKey, JsonWebKeySet, Keystore, PrivateKey}; use mas_oidc_client::{ - http_service::{hyper::hyper_service, HttpService}, + http_service::HttpService, types::{ client_credentials::{ClientCredentials, JwtSigningFn, JwtSigningMethod}, IdToken, @@ -34,6 +36,10 @@ use rand::{ distributions::{Alphanumeric, DistString}, SeedableRng, }; +use tower::{ + util::{MapErrLayer, MapRequestLayer}, + BoxError, Layer, +}; use url::Url; use wiremock::MockServer; @@ -58,7 +64,13 @@ fn now() -> DateTime { } async fn init_test() -> (HttpService, MockServer, Url) { - let http_service = hyper_service(); + let http_service = ( + MapErrLayer::new(BoxError::from), + MapRequestLayer::new(|req: http::Request<_>| req.map(Full::new)), + BodyToBytesResponseLayer, + ) + .layer(mas_http::make_untraced_client()); + let http_service = BoxCloneSyncService::new(http_service); let mock_server = MockServer::start().await; let issuer = Url::parse(&mock_server.uri()).expect("Couldn't parse URL");