From 853ce9afc93a9b033010d5e436f46e170587f6e8 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 18:21:05 +0200 Subject: [PATCH 01/16] Upgrade most HTTP/Hyper crates and make mas-listener work --- Cargo.lock | 220 +++++++++++++++++--------- Cargo.toml | 26 ++- crates/axum-utils/Cargo.toml | 4 +- crates/cli/Cargo.toml | 2 +- crates/handlers/Cargo.toml | 13 +- crates/http/Cargo.toml | 17 +- crates/listener/Cargo.toml | 5 +- crates/listener/examples/demo/main.rs | 5 +- crates/listener/src/server.rs | 70 ++++---- crates/router/Cargo.toml | 2 +- 10 files changed, 233 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b5bb72bb..7e2d5e487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,19 +571,19 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "headers", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.4.0", + "hyper-util", "itoa", "matchit", "memchr", @@ -595,57 +595,64 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-extra" -version = "0.8.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab90e7b70bea63a153137162affb6a0bce26b584c24a4c7885509783e2cf30b" +checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" dependencies = [ "axum", "axum-core", "bytes", - "cookie 0.17.0", + "cookie", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "headers 0.4.0", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "mime", "pin-project-lite", "serde", - "tokio", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "axum-macros" -version = "0.3.8" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" +checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -1039,12 +1046,12 @@ dependencies = [ [[package]] name = "cookie" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ "aes-gcm", - "base64 0.21.7", + "base64 0.22.1", "hkdf", "percent-encoding", "rand", @@ -1054,24 +1061,13 @@ dependencies = [ "version_check", ] -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "cookie_store" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" dependencies = [ - "cookie 0.18.1", + "cookie", "idna 0.5.0", "log", "publicsuffix", @@ -2112,13 +2108,28 @@ checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ "base64 0.21.7", "bytes", - "headers-core", + "headers-core 0.2.0", "http 0.2.12", "httpdate", "mime", "sha1", ] +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core 0.3.0", + "http 1.1.0", + "httpdate", + "mime", + "sha1", +] + [[package]] name = "headers-core" version = "0.2.0" @@ -2128,6 +2139,15 @@ dependencies = [ "http 0.2.12", ] +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.1.0", +] + [[package]] name = "heck" version = "0.4.1" @@ -2320,17 +2340,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.25.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c78f9338483cb7e630c8474b07268983c6bd5acee012e4211f9f7bb21b070" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", - "http 0.2.12", - "hyper 0.14.29", - "rustls 0.22.4", + "http 1.1.0", + "hyper 1.4.0", + "hyper-util", + "rustls 0.23.10", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", + "tower-service", ] [[package]] @@ -2340,12 +2362,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", + "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", "hyper 1.4.0", "pin-project-lite", + "socket2 0.5.7", "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -2899,7 +2926,7 @@ dependencies = [ "rustls-pemfile 2.1.2", "socket2 0.5.7", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tracing", "url", "webpki-roots 0.26.3", @@ -3001,9 +3028,9 @@ dependencies = [ "chrono", "data-encoding", "futures-util", - "headers", - "http 0.2.12", - "http-body 0.4.6", + "headers 0.3.9", + "http 1.1.0", + "http-body 1.0.0", "icu_locid", "mas-data-model", "mas-http", @@ -3041,7 +3068,7 @@ dependencies = [ "dotenvy", "figment", "httpdate", - "hyper 0.14.29", + "hyper 1.4.0", "ipnetwork", "itertools 0.13.0", "listenfd", @@ -3086,7 +3113,7 @@ dependencies = [ "sqlx", "tokio", "tower", - "tower-http", + "tower-http 0.4.4", "tracing", "tracing-appender", "tracing-opentelemetry", @@ -3148,7 +3175,7 @@ name = "mas-email" version = "0.9.0" dependencies = [ "async-trait", - "headers", + "headers 0.3.9", "lettre", "mas-templates", "thiserror", @@ -3172,8 +3199,8 @@ dependencies = [ "chrono", "cookie_store", "futures-util", - "headers", - "hyper 0.14.29", + "headers 0.3.9", + "hyper 1.4.0", "insta", "lettre", "mas-axum-utils", @@ -3210,7 +3237,7 @@ dependencies = [ "time", "tokio", "tower", - "tower-http", + "tower-http 0.4.4", "tracing", "tracing-subscriber", "ulid", @@ -3225,10 +3252,10 @@ dependencies = [ "anyhow", "bytes", "futures-util", - "headers", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "headers 0.3.9", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.4.0", "hyper-rustls", "mas-tower", "opentelemetry", @@ -3241,7 +3268,7 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http", + "tower-http 0.4.4", "tracing", "tracing-opentelemetry", ] @@ -3301,7 +3328,7 @@ dependencies = [ "convert_case", "csv", "futures-util", - "hyper 0.14.29", + "hyper 1.4.0", "serde", "tokio", "tracing", @@ -3376,18 +3403,19 @@ dependencies = [ "bytes", "event-listener 5.3.1", "futures-util", - "http-body 0.4.6", - "hyper 0.14.29", + "http-body 1.0.0", + "hyper 1.4.0", + "hyper-util", "libc", "pin-project-lite", "rustls-pemfile 2.1.2", "socket2 0.5.7", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-test", - "tower-http", - "tower-service", + "tower", + "tower-http 0.5.2", "tracing", "tracing-subscriber", ] @@ -3398,7 +3426,7 @@ version = "0.9.0" dependencies = [ "anyhow", "async-trait", - "http 0.2.12", + "http 1.1.0", "serde", "tokio", "url", @@ -3410,7 +3438,7 @@ version = "0.9.0" dependencies = [ "anyhow", "async-trait", - "http 0.2.12", + "http 1.1.0", "mas-axum-utils", "mas-http", "mas-matrix", @@ -3433,10 +3461,10 @@ dependencies = [ "chrono", "form_urlencoded", "futures-util", - "headers", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "headers 0.3.9", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.4.0", "hyper-rustls", "language-tags", "mas-http", @@ -3456,7 +3484,7 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http", + "tower-http 0.4.4", "tracing", "url", "wiremock", @@ -3592,7 +3620,7 @@ dependencies = [ "arc-swap", "camino", "chrono", - "http 0.2.12", + "http 1.1.0", "mas-data-model", "mas-i18n", "mas-router", @@ -3616,7 +3644,7 @@ dependencies = [ name = "mas-tower" version = "0.9.0" dependencies = [ - "http 0.2.12", + "http 1.1.0", "opentelemetry", "opentelemetry-http", "opentelemetry-semantic-conventions", @@ -3860,7 +3888,7 @@ dependencies = [ "assert_matches", "chrono", "data-encoding", - "http 0.2.12", + "http 1.1.0", "language-tags", "mas-iana", "mas-jose", @@ -4887,6 +4915,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -5841,6 +5882,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "synstructure" version = "0.13.1" @@ -5997,6 +6044,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.10", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -6116,6 +6174,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags 2.6.0", + "bytes", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.2" diff --git a/Cargo.toml b/Cargo.toml index 5635a2316..66e4cabdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,15 @@ version = "0.1.80" [workspace.dependencies.anyhow] version = "1.0.86" +# HTTP router +[workspace.dependencies.axum] +version = "0.7.5" + +# Extra utilities for Axum +[workspace.dependencies.axum-extra] +version = "0.9.3" +features = ["cookie-private", "cookie-key-expansion", "typed-header"] + # UTF-8 paths [workspace.dependencies.camino] version = "1.1.7" @@ -94,20 +103,25 @@ version = "0.3.9" # HTTP request/response [workspace.dependencies.http] -version = "0.2.12" +version = "1.1.0" # HTTP body trait [workspace.dependencies.http-body] -version = "0.4.6" +version = "1.0.0" -# HTTP client +# HTTP client and server [workspace.dependencies.hyper] -version = "0.14.29" -features = ["client", "http1", "http2", "stream", "runtime"] +version = "1.4.0" +features = ["client", "http1", "http2"] + +# Additional Hyper utilties +[workspace.dependencies.hyper-util] +version = "0.1.6" +features = ["server", "server-auto", "service", "http1", "http2", "tokio"] # Hyper Rustls support [workspace.dependencies.hyper-rustls] -version = "0.25.0" +version = "0.27.2" features = ["http1", "http2"] default-features = false diff --git a/crates/axum-utils/Cargo.toml b/crates/axum-utils/Cargo.toml index 833131812..c077d8667 100644 --- a/crates/axum-utils/Cargo.toml +++ b/crates/axum-utils/Cargo.toml @@ -13,8 +13,8 @@ workspace = true [dependencies] async-trait.workspace = true -axum = { version = "0.6.20", features = ["headers"] } -axum-extra = { version = "0.8.0", features = ["cookie-private", "cookie-key-expansion"] } +axum.workspace = true +axum-extra.workspace = true chrono.workspace = true data-encoding = "2.6.0" futures-util = "0.3.30" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index fce8922f4..463948a49 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] anyhow.workspace = true -axum = "0.6.20" +axum.workspace = true camino.workspace = true clap.workspace = true console = "0.15.8" diff --git a/crates/handlers/Cargo.toml b/crates/handlers/Cargo.toml index 3ec443fcb..10d8ff2eb 100644 --- a/crates/handlers/Cargo.toml +++ b/crates/handlers/Cargo.toml @@ -31,9 +31,9 @@ sentry = { version = "0.31.8", default-features = false } hyper.workspace = true tower.workspace = true tower-http = { version = "0.4.4", features = ["cors"] } -axum = "0.6.20" -axum-macros = "0.3.8" -axum-extra = { version = "0.8.0", features = ["cookie-private"] } +axum.workspace = true +axum-macros = "0.4.1" +axum-extra.workspace = true async-graphql.workspace = true @@ -52,7 +52,12 @@ serde_urlencoded = "0.7.1" # Password hashing argon2 = { version = "0.5.3", features = ["password-hash", "std"] } bcrypt = "0.15.1" -pbkdf2 = { version = "0.12.2", features = ["password-hash", "std", "simple", "parallel"] } +pbkdf2 = { version = "0.12.2", features = [ + "password-hash", + "std", + "simple", + "parallel", +] } zeroize = "1.8.1" # Various data types and utilities diff --git a/crates/http/Cargo.toml b/crates/http/Cargo.toml index 6d3c7dfad..dd5b013b1 100644 --- a/crates/http/Cargo.toml +++ b/crates/http/Cargo.toml @@ -40,13 +40,12 @@ tokio.workspace = true [features] client = [ - "dep:mas-tower", - "dep:rustls", - "hyper/tcp", - "dep:hyper-rustls", - "dep:rustls-platform-verifier", - "tower/limit", - "tower-http/timeout", - "tower-http/follow-redirect", - "tower-http/set-header", + "dep:mas-tower", + "dep:rustls", + "dep:hyper-rustls", + "dep:rustls-platform-verifier", + "tower/limit", + "tower-http/timeout", + "tower-http/follow-redirect", + "tower-http/set-header", ] diff --git a/crates/listener/Cargo.toml b/crates/listener/Cargo.toml index a3e64c4ff..79ea0a126 100644 --- a/crates/listener/Cargo.toml +++ b/crates/listener/Cargo.toml @@ -17,14 +17,15 @@ event-listener = "5.3.1" futures-util = "0.3.30" http-body.workspace = true hyper = { workspace = true, features = ["server"] } +hyper-util.workspace = true libc = "0.2.155" pin-project-lite = "0.2.14" socket2 = "0.5.7" thiserror.workspace = true tokio.workspace = true tokio-rustls = "0.25.0" -tower-http = { version = "0.4.4", features = ["add-extension"] } -tower-service = "0.3.2" +tower.workspace = true +tower-http = { version = "0.5.2", features = ["add-extension"] } tracing.workspace = true [dev-dependencies] diff --git a/crates/listener/examples/demo/main.rs b/crates/listener/examples/demo/main.rs index ec65132d5..a24c42ecb 100644 --- a/crates/listener/examples/demo/main.rs +++ b/crates/listener/examples/demo/main.rs @@ -21,16 +21,17 @@ use std::{ }; use anyhow::Context; -use hyper::{service::service_fn, Request, Response}; +use hyper::{Request, Response}; use mas_listener::{server::Server, shutdown::ShutdownStream, ConnectionInfo}; use tokio::signal::unix::SignalKind; use tokio_rustls::rustls::{server::WebPkiClientVerifier, RootCertStore, ServerConfig}; +use tower::service_fn; static CA_CERT_PEM: &[u8] = include_bytes!("./certs/ca.pem"); static SERVER_CERT_PEM: &[u8] = include_bytes!("./certs/server.pem"); static SERVER_KEY_PEM: &[u8] = include_bytes!("./certs/server-key.pem"); -async fn handler(req: Request) -> Result, Infallible> { +async fn handler(req: Request) -> Result, Infallible> { tracing::info!("Handling request"); tokio::time::sleep(Duration::from_secs(3)).await; let info = req.extensions().get::().unwrap(); diff --git a/crates/listener/src/server.rs b/crates/listener/src/server.rs index 69433a4ad..d4e2d6c49 100644 --- a/crates/listener/src/server.rs +++ b/crates/listener/src/server.rs @@ -22,14 +22,17 @@ use std::{ use event_listener::{Event, EventListener}; use futures_util::{stream::SelectAll, Stream, StreamExt}; -use http_body::Body; -use hyper::{body::HttpBody, server::conn::Connection, Request, Response}; +use hyper::{Request, Response}; +use hyper_util::{ + rt::{TokioExecutor, TokioIo}, + server::conn::auto::Connection, + service::TowerToHyperService, +}; use pin_project_lite::pin_project; use thiserror::Error; -use tokio::io::{AsyncRead, AsyncWrite}; use tokio_rustls::rustls::ServerConfig; +use tower::Service; use tower_http::add_extension::AddExtension; -use tower_service::Service; use tracing::Instrument; use crate::{ @@ -91,10 +94,10 @@ impl Server { /// Run a single server pub async fn run(self, shutdown: SD) where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: std::error::Error + Send + Sync + 'static, - B: Body + Send + 'static, + B: http_body::Body + Send + 'static, B::Data: Send, B::Error: std::error::Error + Send + Sync + 'static, SD: Stream + Unpin, @@ -173,15 +176,20 @@ async fn accept( stream: UnixOrTcpConnection, service: S, ) -> Result< - Connection>, AddExtension>, + Connection< + 'static, + TokioIo>>, + TowerToHyperService>, + TokioExecutor, + >, AcceptError, > where - S: Service, Response = Response>, + S: Service, Response = Response> + Send + Clone + 'static, S::Error: std::error::Error + Send + Sync + 'static, S::Future: Send + 'static, - B: HttpBody + Send + 'static, - B::Data: Send + 'static, + B: http_body::Body + Send + 'static, + B::Data: Send, B::Error: std::error::Error + Send + Sync + 'static, { let span = tracing::Span::current(); @@ -219,18 +227,17 @@ where net_peer_addr: peer_addr.into_net(), }; - let service = AddExtension::new(service, info); - - let conn = if is_h2 { - hyper::server::conn::Http::new() - .http2_only(true) - .serve_connection(stream, service) - } else { - hyper::server::conn::Http::new() - .http1_only(true) - .http1_keep_alive(true) - .serve_connection(stream, service) - }; + let mut builder = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new()); + if is_h2 { + builder = builder.http2_only(); + } + builder.http1().keep_alive(true); + + let service = TowerToHyperService::new(AddExtension::new(service, info)); + + let conn = builder + .serve_connection(TokioIo::new(stream), service) + .into_owned(); Ok(conn) }) @@ -270,18 +277,19 @@ impl AbortableConnection { } } -impl Future for AbortableConnection> +impl Future + for AbortableConnection, TokioExecutor>> where - Connection: Future, - S: Service, Response = Response> + Send + 'static, + Connection<'static, T, TowerToHyperService, TokioExecutor>: Future, + S: Service, Response = Response> + Send + Clone + 'static, S::Future: Send + 'static, S::Error: std::error::Error + Send + Sync, - B: HttpBody + Send + 'static, + T: hyper::rt::Read + hyper::rt::Write + Unpin, + B: http_body::Body + Send + 'static, B::Data: Send, - B::Error: std::error::Error + Send + Sync, - T: AsyncRead + AsyncWrite + Unpin, + B::Error: std::error::Error + Send + Sync + 'static, { - type Output = as Future>::Output; + type Output = , TokioExecutor> as Future>::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); @@ -308,10 +316,10 @@ where #[allow(clippy::too_many_lines)] pub async fn run_servers(listeners: impl IntoIterator>, mut shutdown: SD) where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: std::error::Error + Send + Sync + 'static, - B: Body + Send + 'static, + B: http_body::Body + Send + 'static, B::Data: Send, B::Error: std::error::Error + Send + Sync + 'static, SD: Stream + Unpin, diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index b92fa2aae..cde2ad69d 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -12,7 +12,7 @@ publish = false workspace = true [dependencies] -axum = { version = "0.6.20", default-features = false } +axum.workspace = true serde.workspace = true serde_urlencoded = "0.7.1" url.workspace = true From eeb30af3c93a0ac1a2e0ec16a5267ca462c8b3a2 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 18:26:31 +0200 Subject: [PATCH 02/16] Upgrade `headers` and adapt mas-tower tracer context utils --- Cargo.lock | 38 ++++++------------------------- Cargo.toml | 2 +- crates/tower/src/trace_context.rs | 16 ++++++++++++- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e2d5e487..94b1e22d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -635,7 +635,7 @@ dependencies = [ "bytes", "cookie", "futures-util", - "headers 0.4.0", + "headers", "http 1.1.0", "http-body 1.0.0", "http-body-util", @@ -2100,21 +2100,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core 0.2.0", - "http 0.2.12", - "httpdate", - "mime", - "sha1", -] - [[package]] name = "headers" version = "0.4.0" @@ -2123,22 +2108,13 @@ checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ "base64 0.21.7", "bytes", - "headers-core 0.3.0", + "headers-core", "http 1.1.0", "httpdate", "mime", "sha1", ] -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - [[package]] name = "headers-core" version = "0.3.0" @@ -3028,7 +3004,7 @@ dependencies = [ "chrono", "data-encoding", "futures-util", - "headers 0.3.9", + "headers", "http 1.1.0", "http-body 1.0.0", "icu_locid", @@ -3175,7 +3151,7 @@ name = "mas-email" version = "0.9.0" dependencies = [ "async-trait", - "headers 0.3.9", + "headers", "lettre", "mas-templates", "thiserror", @@ -3199,7 +3175,7 @@ dependencies = [ "chrono", "cookie_store", "futures-util", - "headers 0.3.9", + "headers", "hyper 1.4.0", "insta", "lettre", @@ -3252,7 +3228,7 @@ dependencies = [ "anyhow", "bytes", "futures-util", - "headers 0.3.9", + "headers", "http 1.1.0", "http-body 1.0.0", "hyper 1.4.0", @@ -3461,7 +3437,7 @@ dependencies = [ "chrono", "form_urlencoded", "futures-util", - "headers 0.3.9", + "headers", "http 1.1.0", "http-body 1.0.0", "hyper 1.4.0", diff --git a/Cargo.toml b/Cargo.toml index 66e4cabdb..107e82431 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,7 @@ features = ["env", "yaml", "test"] # HTTP headers [workspace.dependencies.headers] -version = "0.3.9" +version = "0.4.0" # HTTP request/response [workspace.dependencies.http] diff --git a/crates/tower/src/trace_context.rs b/crates/tower/src/trace_context.rs index c203e374d..83b1cee03 100644 --- a/crates/tower/src/trace_context.rs +++ b/crates/tower/src/trace_context.rs @@ -14,11 +14,25 @@ use http::Request; use opentelemetry::propagation::Injector; -use opentelemetry_http::HeaderInjector; use tower::{Layer, Service}; use tracing::Span; use tracing_opentelemetry::OpenTelemetrySpanExt; +/// Same as the one in opentelemetry-http, but updated for the http@1 upgrade +pub struct HeaderInjector<'a>(pub &'a mut http::HeaderMap); + +impl<'a> Injector for HeaderInjector<'a> { + /// Set a key and value in the [`HeaderMap`]. Does nothing if the key or + /// value are not valid inputs. + fn set(&mut self, key: &str, value: String) { + if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) { + if let Ok(val) = http::header::HeaderValue::from_str(&value) { + self.0.insert(name, val); + } + } + } +} + /// A trait to get an [`Injector`] from a request. trait AsInjector { type Injector<'a>: Injector From 697c81cedff31aee04be1680469397e0c65c178d Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 18:38:38 +0200 Subject: [PATCH 03/16] Update mas-iana-codegen to use reqwest --- Cargo.lock | 178 +++++++++++++++++++++++++++++- crates/iana-codegen/Cargo.toml | 4 +- crates/iana-codegen/src/main.rs | 16 ++- crates/iana-codegen/src/traits.rs | 13 +-- 4 files changed, 192 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94b1e22d7..49a123c97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1776,6 +1776,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2331,6 +2346,22 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.4.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.6" @@ -2727,6 +2758,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "ipnetwork" version = "0.20.0" @@ -3304,7 +3341,7 @@ dependencies = [ "convert_case", "csv", "futures-util", - "hyper 1.4.0", + "reqwest", "serde", "tokio", "tracing", @@ -3764,6 +3801,23 @@ dependencies = [ "version_check", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nom" version = "7.1.3" @@ -3935,12 +3989,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry" version = "0.23.0" @@ -4763,6 +4855,49 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.4.0", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.2", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -5875,6 +6010,27 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "target-lexicon" version = "0.12.14" @@ -6009,6 +6165,16 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.25.0" @@ -7040,6 +7206,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wiremock" version = "0.6.0" diff --git a/crates/iana-codegen/Cargo.toml b/crates/iana-codegen/Cargo.toml index 8b2fdab2d..d5da9ebaf 100644 --- a/crates/iana-codegen/Cargo.toml +++ b/crates/iana-codegen/Cargo.toml @@ -18,8 +18,8 @@ camino.workspace = true convert_case = "0.6.0" csv = "1.3.0" futures-util = "0.3.30" -hyper.workspace = true +reqwest = "0.12.5" serde.workspace = true -tokio.workspace= true +tokio.workspace = true tracing.workspace = true tracing-subscriber.workspace = true diff --git a/crates/iana-codegen/src/main.rs b/crates/iana-codegen/src/main.rs index 398937731..7d97e3785 100644 --- a/crates/iana-codegen/src/main.rs +++ b/crates/iana-codegen/src/main.rs @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{collections::HashMap, fmt::Display, sync::Arc}; +use std::{collections::HashMap, fmt::Display}; use camino::{Utf8Path, Utf8PathBuf}; +use reqwest::Client; use tokio::io::AsyncWriteExt; use tracing::Level; -type Client = hyper::Client; - mod gen; pub mod jose; pub mod oauth; @@ -27,7 +26,7 @@ pub mod traits; #[derive(Debug)] struct File { - client: Arc, + client: Client, registry_name: &'static str, registry_url: &'static str, sections: Vec
, @@ -42,7 +41,7 @@ fn resolve_path(relative: impl AsRef) -> Utf8PathBuf { impl File { #[tracing::instrument(skip(client))] - fn new(registry_name: &'static str, registry_url: &'static str, client: Arc) -> Self { + fn new(registry_name: &'static str, registry_url: &'static str, client: Client) -> Self { tracing::info!("Generating file from IANA registry"); Self { client, @@ -142,7 +141,7 @@ use self::traits::{EnumEntry, EnumMember, Section}; #[tracing::instrument(skip_all, fields(%path))] async fn generate_jose( - client: &Arc, + client: &Client, path: impl AsRef + std::fmt::Display, ) -> anyhow::Result<()> { let path = resolve_path(path); @@ -173,7 +172,7 @@ async fn generate_jose( #[tracing::instrument(skip_all, fields(%path))] async fn generate_oauth( - client: &Arc, + client: &Client, path: impl AsRef + std::fmt::Display, ) -> anyhow::Result<()> { let path = resolve_path(path); @@ -182,7 +181,7 @@ async fn generate_oauth( let file = File::new( "OAuth Parameters", "https://www.iana.org/assignments/jose/jose.xhtml", - client.clone(), + client, ) .load::() .await? @@ -208,7 +207,6 @@ async fn main() -> anyhow::Result<()> { .init(); let client = Client::new(); - let client = Arc::new(client); let iana_crate_root = Utf8Path::new("crates/iana/"); diff --git a/crates/iana-codegen/src/traits.rs b/crates/iana-codegen/src/traits.rs index 7c9006082..d4ecfd394 100644 --- a/crates/iana-codegen/src/traits.rs +++ b/crates/iana-codegen/src/traits.rs @@ -15,7 +15,6 @@ use anyhow::Context; use async_trait::async_trait; use convert_case::{Case, Casing}; -use hyper::http; use serde::de::DeserializeOwned; use super::Client; @@ -74,23 +73,23 @@ pub trait EnumEntry: DeserializeOwned + Send + Sync { async fn fetch(client: &Client) -> anyhow::Result> { tracing::info!("Fetching CSV"); - let request = http::Request::get(Self::URL) - .header("User-Agent", "mas-iana-codegen/0.1") - .body(hyper::Body::empty())?; let response = client - .request(request) + .get(Self::URL) + .header("User-Agent", "mas-iana-codegen/0.1") + .send() .await .context(format!("can't the CSV at {}", Self::URL))?; let status = response.status(); anyhow::ensure!(status.is_success(), "HTTP status code is not 200: {status}"); - let body = hyper::body::to_bytes(response.into_body()) + let body = response + .text() .await .context(format!("can't the CSV body at {}", Self::URL))?; - let parsed: Result, _> = csv::Reader::from_reader(body.as_ref()) + let parsed: Result, _> = csv::Reader::from_reader(body.as_bytes()) .into_deserialize() .filter_map(|item: Result| { item.map(|item| { From 81ed71c8f94895a2bfcd6d2e4f1c782ac1e1c12c Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 19:02:29 +0200 Subject: [PATCH 04/16] Upgrade rustls and update mas-http client bits --- Cargo.lock | 232 ++++++++++++++---- Cargo.toml | 20 +- crates/http/Cargo.toml | 4 +- crates/http/src/client.rs | 19 +- .../http/src/layers/body_to_bytes_response.rs | 3 +- .../http/src/layers/bytes_to_body_request.rs | 2 +- crates/http/src/lib.rs | 2 +- crates/listener/Cargo.toml | 2 +- 8 files changed, 224 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49a123c97..34979ed43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,6 +569,32 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "aws-lc-rs" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33e4a55b03f8780ba55041bc7be91a2a8ec8c03517b0379d2d6c96d2c30d95" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ede3d6e360a48436fee127cb81710834407b1ec0c48a001cc29dec9005f73e" +dependencies = [ + "bindgen", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "axum" version = "0.7.5" @@ -718,6 +744,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.68", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -850,6 +899,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -945,6 +1003,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.8" @@ -985,6 +1054,15 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "cobs" version = "0.2.3" @@ -1520,6 +1598,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "duration-str" version = "0.11.2" @@ -1583,9 +1667,9 @@ dependencies = [ [[package]] name = "email-encoding" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a87260449b06739ee78d6281c68d2a0ff3e3af64a78df63d3a1aeb3c06997c8a" +checksum = "60d1d33cdaede7e24091f039632eb5d3c7469fe5b066a985281a34fc70fa317f" dependencies = [ "base64 0.22.1", "memchr", @@ -1800,6 +1884,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.30" @@ -2210,6 +2300,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows", +] + [[package]] name = "http" version = "0.2.12" @@ -2342,7 +2443,7 @@ dependencies = [ "rustls 0.23.10", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", ] @@ -2907,6 +3008,12 @@ dependencies = [ "spin", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "leb128" version = "0.2.5" @@ -2915,31 +3022,31 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "lettre" -version = "0.11.4" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357ff5edb6d8326473a64c82cf41ddf78ab116f89668c50c4fac1b321e5e80f4" +checksum = "1a62049a808f1c4e2356a2a380bd5f2aca3b011b0b482cf3b914ba1731426969" dependencies = [ "async-std", "async-trait", - "base64 0.21.7", + "base64 0.22.1", "chumsky", "email-encoding", "email_address", "fastrand 2.1.0", "futures-io", "futures-util", - "hostname", + "hostname 0.4.0", "httpdate", "idna 0.5.0", "mime", "nom", "percent-encoding", "quoted_printable", - "rustls 0.22.4", + "rustls 0.23.10", "rustls-pemfile 2.1.2", "socket2 0.5.7", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tracing", "url", "webpki-roots 0.26.3", @@ -2951,6 +3058,16 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libloading" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + [[package]] name = "libm" version = "0.2.8" @@ -3117,7 +3234,7 @@ dependencies = [ "prometheus", "rand", "rand_chacha", - "rustls 0.22.4", + "rustls 0.23.10", "sentry", "sentry-tower", "sentry-tracing", @@ -3268,12 +3385,14 @@ dependencies = [ "headers", "http 1.1.0", "http-body 1.0.0", + "http-body-util", "hyper 1.4.0", "hyper-rustls", + "hyper-util", "mas-tower", "opentelemetry", "opentelemetry-semantic-conventions", - "rustls 0.22.4", + "rustls 0.23.10", "rustls-platform-verifier", "serde", "serde_json", @@ -3281,7 +3400,7 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http 0.4.4", + "tower-http 0.5.2", "tracing", "tracing-opentelemetry", ] @@ -3425,7 +3544,7 @@ dependencies = [ "socket2 0.5.7", "thiserror", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tokio-test", "tower", "tower-http 0.5.2", @@ -3488,7 +3607,7 @@ dependencies = [ "oauth2-types", "rand", "rand_chacha", - "rustls 0.22.4", + "rustls 0.23.10", "rustls-platform-verifier", "serde", "serde_json", @@ -3783,6 +3902,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "multer" version = "2.1.0" @@ -4587,6 +4712,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn 2.0.68", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -5012,27 +5147,16 @@ dependencies = [ "sct", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.4", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" dependencies = [ + "aws-lc-rs", + "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.102.4", "subtle", @@ -5079,16 +5203,16 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-platform-verifier" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c35b9a497e588f1fb2e1d18a0d46a6d057710f34c3da7084b27353b319453cc" +checksum = "3e3beb939bcd33c269f4bf946cc829fcd336370267c4a927ac0399c84a3151a1" dependencies = [ "core-foundation", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.22.4", + "rustls 0.23.10", "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.102.4", @@ -5120,6 +5244,7 @@ version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -5350,7 +5475,7 @@ version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6436c1bad22cdeb02179ea8ef116ffc217797c028927def303bc593d9320c0d1" dependencies = [ - "hostname", + "hostname 0.3.1", "libc", "os_info", "rustc_version", @@ -5569,6 +5694,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -6175,17 +6306,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" @@ -6324,10 +6444,14 @@ checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.6.0", "bytes", + "futures-util", "http 1.1.0", "http-body 1.0.0", "http-body-util", + "iri-string", "pin-project-lite", + "tokio", + "tower", "tower-layer", "tower-service", ] @@ -6999,6 +7123,18 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.34", +] + [[package]] name = "whoami" version = "1.5.1" @@ -7040,6 +7176,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 107e82431..e5a373dd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -109,6 +109,10 @@ version = "1.1.0" [workspace.dependencies.http-body] version = "1.0.0" +# http-body utilities +[workspace.dependencies.http-body-util] +version = "0.1.2" + # HTTP client and server [workspace.dependencies.hyper] version = "1.4.0" @@ -117,7 +121,15 @@ features = ["client", "http1", "http2"] # Additional Hyper utilties [workspace.dependencies.hyper-util] version = "0.1.6" -features = ["server", "server-auto", "service", "http1", "http2", "tokio"] +features = [ + "client", + "server", + "server-auto", + "service", + "http1", + "http2", + "tokio", +] # Hyper Rustls support [workspace.dependencies.hyper-rustls] @@ -127,7 +139,7 @@ default-features = false # Email sending [workspace.dependencies.lettre] -version = "=0.11.4" +version = "0.11.7" default-features = false features = [ "tokio1-rustls-tls", @@ -149,11 +161,11 @@ version = "0.8.5" # TLS stack [workspace.dependencies.rustls] -version = "0.22.4" +version = "0.23.10" # Use platform-specific verifier for TLS [workspace.dependencies.rustls-platform-verifier] -version = "0.2.0" +version = "0.3.1" # JSON Schema generation [workspace.dependencies.schemars] diff --git a/crates/http/Cargo.toml b/crates/http/Cargo.toml index dd5b013b1..c0692fcc5 100644 --- a/crates/http/Cargo.toml +++ b/crates/http/Cargo.toml @@ -17,7 +17,9 @@ futures-util = "0.3.30" headers.workspace = true http.workspace = true http-body.workspace = true +http-body-util.workspace = true hyper.workspace = true +hyper-util.workspace = true hyper-rustls = { workspace = true, optional = true } opentelemetry.workspace = true opentelemetry-semantic-conventions.workspace = true @@ -28,7 +30,7 @@ serde_json.workspace = true serde_urlencoded = "0.7.1" thiserror.workspace = true tower.workspace = true -tower-http = { version = "0.4.4", features = ["cors"] } +tower-http = { version = "0.5.2", features = ["cors"] } tracing.workspace = true tracing-opentelemetry.workspace = true diff --git a/crates/http/src/client.rs b/crates/http/src/client.rs index a24b06926..f227e35c0 100644 --- a/crates/http/src/client.rs +++ b/crates/http/src/client.rs @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use hyper::client::{ - connect::dns::{GaiResolver, Name}, - HttpConnector, -}; -pub use hyper::Client; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; +pub use hyper_util::client::legacy::Client; +use hyper_util::{ + client::legacy::connect::{ + dns::{GaiResolver, Name}, + HttpConnector, + }, + rt::TokioExecutor, +}; use mas_tower::{ DurationRecorderLayer, DurationRecorderService, FnWrapper, InFlightCounterLayer, InFlightCounterService, TraceLayer, TraceService, @@ -26,8 +29,8 @@ use opentelemetry_semantic_conventions::trace::SERVER_ADDRESS; use tower::Layer; use tracing::Span; -pub type UntracedClient = hyper::Client; -pub type TracedClient = hyper::Client; +pub type UntracedClient = Client; +pub type TracedClient = Client; /// Create a basic Hyper HTTP & HTTPS client without any tracing #[must_use] @@ -37,7 +40,7 @@ where B::Data: Send, { let https = make_untraced_connector(); - Client::builder().build(https) + Client::builder(TokioExecutor::new()).build(https) } pub type TraceResolver = diff --git a/crates/http/src/layers/body_to_bytes_response.rs b/crates/http/src/layers/body_to_bytes_response.rs index 1ebb3d93b..4bf01d3b3 100644 --- a/crates/http/src/layers/body_to_bytes_response.rs +++ b/crates/http/src/layers/body_to_bytes_response.rs @@ -16,6 +16,7 @@ use bytes::Bytes; use futures_util::future::BoxFuture; use http::{Request, Response}; use http_body::Body; +use http_body_util::BodyExt; use thiserror::Error; use tower::{Layer, Service}; @@ -82,7 +83,7 @@ where let response = inner.await.map_err(Error::service)?; let (parts, body) = response.into_parts(); - let body = hyper::body::to_bytes(body).await.map_err(Error::body)?; + let body = body.collect().await.map_err(Error::body)?.to_bytes(); let response = Response::from_parts(parts, body); Ok(response) diff --git a/crates/http/src/layers/bytes_to_body_request.rs b/crates/http/src/layers/bytes_to_body_request.rs index 8c8586c2d..8e8b2750a 100644 --- a/crates/http/src/layers/bytes_to_body_request.rs +++ b/crates/http/src/layers/bytes_to_body_request.rs @@ -14,7 +14,7 @@ use bytes::Bytes; use http::Request; -use http_body::Full; +use http_body_util::Full; use tower::{Layer, Service}; #[derive(Clone)] diff --git a/crates/http/src/lib.rs b/crates/http/src/lib.rs index 916208fdd..48b7f801c 100644 --- a/crates/http/src/lib.rs +++ b/crates/http/src/lib.rs @@ -44,4 +44,4 @@ pub use self::{ service::{BoxCloneSyncService, HttpService}, }; -pub type EmptyBody = http_body::Empty; +pub type EmptyBody = http_body_util::Empty; diff --git a/crates/listener/Cargo.toml b/crates/listener/Cargo.toml index 79ea0a126..f39b708bf 100644 --- a/crates/listener/Cargo.toml +++ b/crates/listener/Cargo.toml @@ -23,7 +23,7 @@ pin-project-lite = "0.2.14" socket2 = "0.5.7" thiserror.workspace = true tokio.workspace = true -tokio-rustls = "0.25.0" +tokio-rustls = "0.26.0" tower.workspace = true tower-http = { version = "0.5.2", features = ["add-extension"] } tracing.workspace = true From ff064c0d64573f72d096ba12283410415a914556 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 19:18:15 +0200 Subject: [PATCH 05/16] Remove the client features from mas-oidc-client and replace it in tests --- Cargo.lock | 9 +-- crates/http/src/layers/client.rs | 2 +- crates/oidc-client/Cargo.toml | 26 ++----- .../{http_service/mod.rs => http_service.rs} | 3 - crates/oidc-client/src/http_service/hyper.rs | 69 ------------------- crates/oidc-client/tests/it/main.rs | 16 ++++- 6 files changed, 20 insertions(+), 105 deletions(-) rename crates/oidc-client/src/{http_service/mod.rs => http_service.rs} (94%) delete mode 100644 crates/oidc-client/src/http_service/hyper.rs diff --git a/Cargo.lock b/Cargo.lock index 34979ed43..2543501a9 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 a3f51eb18..bd055fb80 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 cdd4a1b37..6332b04dc 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 4051f5b5f..658b487ba 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 ee9f0ad3f..000000000 --- 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 6edf90a7e..e818ac5bb 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"); From 4a25fac833901aaeab18de83f6bcb857d321452d Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Mon, 1 Jul 2024 19:30:51 +0200 Subject: [PATCH 06/16] Fix the mas-http tests --- crates/http/tests/client_layers.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/http/tests/client_layers.rs b/crates/http/tests/client_layers.rs index f04eb744a..a9c7e0998 100644 --- a/crates/http/tests/client_layers.rs +++ b/crates/http/tests/client_layers.rs @@ -18,6 +18,7 @@ use anyhow::{bail, Context}; use bytes::{Buf, Bytes}; use headers::{ContentType, HeaderMapExt}; use http::{header::ACCEPT, HeaderValue, Request, Response, StatusCode}; +use http_body_util::{BodyExt, Empty}; use mas_http::{ BodyToBytesResponseLayer, BytesToBodyRequestLayer, CatchHttpCodesLayer, FormUrlencodedRequestLayer, JsonRequestLayer, JsonResponseLayer, @@ -51,7 +52,7 @@ async fn test_http_errors() { ); let svc = layer.layer(service_fn(handle)); - let request = Request::new(hyper::Body::empty()); + let request = Request::new(Empty::::new()); let res = svc.oneshot(request).await; let err = res.expect_err("the request should fail"); @@ -60,7 +61,7 @@ async fn test_http_errors() { #[tokio::test] async fn test_json_request_body() { - async fn handle(request: Request) -> Result, anyhow::Error> + async fn handle(request: Request) -> Result>, anyhow::Error> where B: http_body::Body + Send, B::Error: std::error::Error + Send + Sync + 'static, @@ -74,12 +75,12 @@ async fn test_json_request_body() { bail!("Content-Type header is not application/json") } - let bytes = hyper::body::to_bytes(request.into_body()).await?; + let bytes = request.into_body().collect().await?.to_bytes(); if bytes.to_vec() != br#"{"hello":"world"}"#.to_vec() { bail!("Body mismatch") } - let res = Response::new(hyper::Body::empty()); + let res = Response::new(Empty::new()); Ok(res) } @@ -111,7 +112,7 @@ async fn test_json_response_body() { let layer = (JsonResponseLayer::default(), BodyToBytesResponseLayer); let svc = layer.layer(service_fn(handle)); - let request = Request::new(hyper::Body::empty()); + let request = Request::new(Empty::::new()); let res = svc.oneshot(request).await; let response = res.expect("the request to succeed"); @@ -121,7 +122,7 @@ async fn test_json_response_body() { #[tokio::test] async fn test_urlencoded_request_body() { - async fn handle(request: Request) -> Result, anyhow::Error> + async fn handle(request: Request) -> Result>, anyhow::Error> where B: http_body::Body + Send, B::Error: std::error::Error + Send + Sync + 'static, @@ -135,10 +136,10 @@ async fn test_urlencoded_request_body() { bail!("Content-Type header is not application/x-form-urlencoded") } - let bytes = hyper::body::to_bytes(request.into_body()).await?; + let bytes = request.into_body().collect().await?.to_bytes(); assert_eq!(bytes.to_vec(), br"hello=world".to_vec()); - let res = Response::new(hyper::Body::empty()); + let res = Response::new(Empty::new()); Ok(res) } From c21642d616841d69c5161b0d79c146ecbce98ab7 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 10:38:05 +0200 Subject: [PATCH 07/16] Move tower-http dep to the workspace and adapt mas-axum-utils We removed here the Timeout layer on the HTTP client service, because it required the body to be Default, which isn't the case anymore. Not sure what to do about it. --- Cargo.lock | 48 +++++++------------ Cargo.toml | 5 ++ crates/axum-utils/Cargo.toml | 3 ++ crates/axum-utils/src/client_authorization.rs | 16 +++---- crates/axum-utils/src/fancy_error.rs | 3 +- crates/axum-utils/src/http_client_factory.rs | 7 +-- crates/axum-utils/src/jwt.rs | 6 +-- crates/axum-utils/src/user_authorization.rs | 17 ++++--- crates/cli/Cargo.toml | 2 +- crates/handlers/Cargo.toml | 2 +- crates/http/Cargo.toml | 3 +- crates/http/src/layers/client.rs | 10 +--- crates/listener/Cargo.toml | 2 +- 13 files changed, 56 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2543501a9..6c18ea3be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2369,9 +2369,9 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" @@ -3155,12 +3155,15 @@ dependencies = [ "async-trait", "axum", "axum-extra", + "bytes", "chrono", "data-encoding", "futures-util", "headers", "http 1.1.0", "http-body 1.0.0", + "http-body-util", + "hyper-util", "icu_locid", "mas-data-model", "mas-http", @@ -3243,7 +3246,7 @@ dependencies = [ "sqlx", "tokio", "tower", - "tower-http 0.4.4", + "tower-http", "tracing", "tracing-appender", "tracing-opentelemetry", @@ -3367,7 +3370,7 @@ dependencies = [ "time", "tokio", "tower", - "tower-http 0.4.4", + "tower-http", "tracing", "tracing-subscriber", "ulid", @@ -3392,6 +3395,7 @@ dependencies = [ "mas-tower", "opentelemetry", "opentelemetry-semantic-conventions", + "pin-project-lite", "rustls 0.23.10", "rustls-platform-verifier", "serde", @@ -3400,7 +3404,7 @@ dependencies = [ "thiserror", "tokio", "tower", - "tower-http 0.5.2", + "tower-http", "tracing", "tracing-opentelemetry", ] @@ -3547,7 +3551,7 @@ dependencies = [ "tokio-rustls", "tokio-test", "tower", - "tower-http 0.5.2", + "tower-http", "tracing", "tracing-subscriber", ] @@ -6404,31 +6408,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" -dependencies = [ - "bitflags 2.6.0", - "bytes", - "futures-core", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "http-range-header", - "httpdate", - "mime", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower-http" version = "0.5.2" @@ -6441,12 +6420,19 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", + "http-range-header", + "httpdate", "iri-string", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e5a373dd8..b002bed1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -209,6 +209,11 @@ features = ["full"] version = "0.4.13" features = ["util"] +# Tower HTTP layers +[workspace.dependencies.tower-http] +version = "0.5.2" +features = ["cors", "fs", "add-extension"] + # Logging and tracing [workspace.dependencies.tracing] version = "0.1.40" diff --git a/crates/axum-utils/Cargo.toml b/crates/axum-utils/Cargo.toml index c077d8667..00384864c 100644 --- a/crates/axum-utils/Cargo.toml +++ b/crates/axum-utils/Cargo.toml @@ -15,12 +15,15 @@ workspace = true async-trait.workspace = true axum.workspace = true axum-extra.workspace = true +bytes = "1.6.0" chrono.workspace = true data-encoding = "2.6.0" futures-util = "0.3.30" headers.workspace = true http.workspace = true http-body.workspace = true +http-body-util.workspace = true +hyper-util.workspace = true icu_locid = "1.4.0" mime = "0.3.17" rand.workspace = true diff --git a/crates/axum-utils/src/client_authorization.rs b/crates/axum-utils/src/client_authorization.rs index 0f191e44a..d716b0dc9 100644 --- a/crates/axum-utils/src/client_authorization.rs +++ b/crates/axum-utils/src/client_authorization.rs @@ -16,14 +16,14 @@ use std::collections::HashMap; use async_trait::async_trait; use axum::{ - body::HttpBody, extract::{ - rejection::{FailedToDeserializeForm, FormRejection, TypedHeaderRejectionReason}, - Form, FromRequest, FromRequestParts, TypedHeader, + rejection::{FailedToDeserializeForm, FormRejection}, + Form, FromRequest, FromRequestParts, }, response::IntoResponse, BoxError, Json, }; +use axum_extra::typed_header::{TypedHeader, TypedHeaderRejectionReason}; use headers::{authorization::Basic, Authorization}; use http::{Request, StatusCode}; use mas_data_model::{Client, JwksOrJwksUri}; @@ -337,18 +337,18 @@ impl IntoResponse for ClientAuthorizationError { } #[async_trait] -impl FromRequest for ClientAuthorization +impl FromRequest for ClientAuthorization where F: DeserializeOwned, - B: HttpBody + Send + 'static, - B::Data: Send, - B::Error: Into, S: Send + Sync, { type Rejection = ClientAuthorizationError; #[allow(clippy::too_many_lines)] - async fn from_request(req: Request, state: &S) -> Result { + async fn from_request( + req: Request, + state: &S, + ) -> Result { // Split the request into parts so we can extract some headers let (mut parts, body) = req.into_parts(); diff --git a/crates/axum-utils/src/fancy_error.rs b/crates/axum-utils/src/fancy_error.rs index bad289bda..ccdca7391 100644 --- a/crates/axum-utils/src/fancy_error.rs +++ b/crates/axum-utils/src/fancy_error.rs @@ -15,8 +15,9 @@ use axum::{ http::StatusCode, response::{IntoResponse, Response}, - Extension, TypedHeader, + Extension, }; +use axum_extra::typed_header::TypedHeader; use headers::ContentType; use mas_templates::ErrorContext; diff --git a/crates/axum-utils/src/http_client_factory.rs b/crates/axum-utils/src/http_client_factory.rs index 78a812acf..bcdc9c144 100644 --- a/crates/axum-utils/src/http_client_factory.rs +++ b/crates/axum-utils/src/http_client_factory.rs @@ -1,4 +1,4 @@ -// Copyright 2022 The Matrix.org Foundation C.I.C. +// Copyright 2022-2024 The Matrix.org Foundation C.I.C. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::body::Full; +use http_body_util::Full; +use hyper_util::rt::TokioExecutor; use mas_http::{ make_traced_connector, BodyToBytesResponseLayer, Client, ClientLayer, ClientService, HttpService, TracedClient, TracedConnector, @@ -50,7 +51,7 @@ impl HttpClientFactory { B: axum::body::HttpBody + Send, B::Data: Send, { - let client = Client::builder().build(self.traced_connector.clone()); + let client = Client::builder(TokioExecutor::new()).build(self.traced_connector.clone()); self.client_layer .clone() .with_category(category) diff --git a/crates/axum-utils/src/jwt.rs b/crates/axum-utils/src/jwt.rs index eea1c90de..6af0529fe 100644 --- a/crates/axum-utils/src/jwt.rs +++ b/crates/axum-utils/src/jwt.rs @@ -12,10 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::{ - response::{IntoResponse, Response}, - TypedHeader, -}; +use axum::response::{IntoResponse, Response}; +use axum_extra::typed_header::TypedHeader; use headers::ContentType; use mas_jose::jwt::Jwt; use mime::Mime; diff --git a/crates/axum-utils/src/user_authorization.rs b/crates/axum-utils/src/user_authorization.rs index 9181428af..e56c23e3c 100644 --- a/crates/axum-utils/src/user_authorization.rs +++ b/crates/axum-utils/src/user_authorization.rs @@ -16,14 +16,13 @@ use std::{collections::HashMap, error::Error}; use async_trait::async_trait; use axum::{ - body::HttpBody, extract::{ - rejection::{FailedToDeserializeForm, FormRejection, TypedHeaderRejectionReason}, - Form, FromRequest, FromRequestParts, TypedHeader, + rejection::{FailedToDeserializeForm, FormRejection}, + Form, FromRequest, FromRequestParts, }, response::{IntoResponse, Response}, - BoxError, }; +use axum_extra::typed_header::{TypedHeader, TypedHeaderRejectionReason}; use headers::{authorization::Bearer, Authorization, Header, HeaderMapExt, HeaderName}; use http::{header::WWW_AUTHENTICATE, HeaderMap, HeaderValue, Request, StatusCode}; use mas_data_model::Session; @@ -289,17 +288,17 @@ where } #[async_trait] -impl FromRequest for UserAuthorization +impl FromRequest for UserAuthorization where F: DeserializeOwned, - B: HttpBody + Send + 'static, - B::Data: Send, - B::Error: Into, S: Send + Sync, { type Rejection = UserAuthorizationError; - async fn from_request(req: Request, state: &S) -> Result { + async fn from_request( + req: Request, + state: &S, + ) -> Result { let (mut parts, body) = req.into_parts(); let header = TypedHeader::>::from_request_parts(&mut parts, state).await; diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 463948a49..14032a5da 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -33,7 +33,7 @@ serde_yaml = "0.9.34" sqlx.workspace = true tokio.workspace = true tower.workspace = true -tower-http = { version = "0.4.4", features = ["fs"] } +tower-http.workspace = true url.workspace = true zeroize = "1.8.1" diff --git a/crates/handlers/Cargo.toml b/crates/handlers/Cargo.toml index 10d8ff2eb..98b2c7281 100644 --- a/crates/handlers/Cargo.toml +++ b/crates/handlers/Cargo.toml @@ -30,7 +30,7 @@ sentry = { version = "0.31.8", default-features = false } # Web server hyper.workspace = true tower.workspace = true -tower-http = { version = "0.4.4", features = ["cors"] } +tower-http.workspace = true axum.workspace = true axum-macros = "0.4.1" axum-extra.workspace = true diff --git a/crates/http/Cargo.toml b/crates/http/Cargo.toml index c0692fcc5..2d336d3bf 100644 --- a/crates/http/Cargo.toml +++ b/crates/http/Cargo.toml @@ -25,12 +25,13 @@ opentelemetry.workspace = true opentelemetry-semantic-conventions.workspace = true rustls = { workspace = true, optional = true } rustls-platform-verifier = { workspace = true, optional = true } +pin-project-lite = "0.2.14" serde.workspace = true serde_json.workspace = true serde_urlencoded = "0.7.1" thiserror.workspace = true tower.workspace = true -tower-http = { version = "0.5.2", features = ["cors"] } +tower-http.workspace = true tracing.workspace = true tracing-opentelemetry.workspace = true diff --git a/crates/http/src/layers/client.rs b/crates/http/src/layers/client.rs index bd055fb80..7ca42d7a3 100644 --- a/crates/http/src/layers/client.rs +++ b/crates/http/src/layers/client.rs @@ -1,4 +1,4 @@ -// Copyright 2022 The Matrix.org Foundation C.I.C. +// Copyright 2022-2024 The Matrix.org Foundation C.I.C. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::time::Duration; - use headers::{ContentLength, HeaderMapExt, Host, UserAgent}; use http::{header::USER_AGENT, HeaderValue, Request, Response}; use hyper_util::client::legacy::connect::HttpInfo; @@ -35,7 +33,6 @@ use tower::{ use tower_http::{ follow_redirect::{FollowRedirect, FollowRedirectLayer}, set_header::{SetRequestHeader, SetRequestHeaderLayer}, - timeout::{Timeout, TimeoutLayer}, }; use tracing::Span; @@ -45,7 +42,7 @@ pub type ClientService = SetRequestHeader< ConcurrencyLimit< FollowRedirect< TraceService< - TraceContextService>, + TraceContextService, MakeSpanForRequest, EnrichSpanOnResponse, EnrichSpanOnError, @@ -183,7 +180,6 @@ pub struct ClientLayer { follow_redirect_layer: FollowRedirectLayer, trace_layer: TraceLayer, trace_context_layer: TraceContextLayer, - timeout_layer: TimeoutLayer, duration_recorder_layer: DurationRecorderLayer, in_flight_counter_layer: InFlightCounterLayer, } @@ -208,7 +204,6 @@ impl ClientLayer { .on_response(EnrichSpanOnResponse) .on_error(EnrichSpanOnError), trace_context_layer: TraceContextLayer::new(), - timeout_layer: TimeoutLayer::new(Duration::from_secs(10)), duration_recorder_layer: DurationRecorderLayer::new("http.client.duration") .on_request(OnRequestLabels::default()) .on_response(OnResponseLabels) @@ -253,7 +248,6 @@ where &self.follow_redirect_layer, &self.trace_layer, &self.trace_context_layer, - &self.timeout_layer, ) .layer(inner) } diff --git a/crates/listener/Cargo.toml b/crates/listener/Cargo.toml index f39b708bf..d15ea9a6c 100644 --- a/crates/listener/Cargo.toml +++ b/crates/listener/Cargo.toml @@ -25,7 +25,7 @@ thiserror.workspace = true tokio.workspace = true tokio-rustls = "0.26.0" tower.workspace = true -tower-http = { version = "0.5.2", features = ["add-extension"] } +tower-http.workspace = true tracing.workspace = true [dev-dependencies] From 056a8839efd7331bfb1cfb44d90e103a52cce06c Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 11:55:40 +0200 Subject: [PATCH 08/16] Upgrade async-graphql, fix mas-handlers & mas-axum-utils tests This also replaces the init_tracing test helper with a general setup test helper, so that it also initializes the rustls crypto backend. --- Cargo.lock | 83 +++++++++++-------- Cargo.toml | 2 +- crates/axum-utils/src/client_authorization.rs | 20 ++--- crates/handlers/Cargo.toml | 1 + crates/handlers/src/compat/login.rs | 15 ++-- crates/handlers/src/compat/logout.rs | 3 +- crates/handlers/src/graphql/mod.rs | 9 +- crates/handlers/src/graphql/tests.rs | 26 +++--- crates/handlers/src/lib.rs | 34 ++------ .../handlers/src/oauth2/device/authorize.rs | 7 +- crates/handlers/src/oauth2/discovery.rs | 4 +- crates/handlers/src/oauth2/introspection.rs | 6 +- crates/handlers/src/oauth2/registration.rs | 6 +- crates/handlers/src/oauth2/revoke.rs | 4 +- crates/handlers/src/oauth2/token.rs | 15 ++-- crates/handlers/src/oauth2/webfinger.rs | 3 +- crates/handlers/src/preferred_language.rs | 2 +- crates/handlers/src/test_utils.rs | 15 ++-- crates/handlers/src/upstream_oauth2/cache.rs | 6 +- crates/handlers/src/upstream_oauth2/link.rs | 9 +- crates/handlers/src/views/login.rs | 8 +- crates/handlers/src/views/recovery/start.rs | 3 +- crates/handlers/src/views/register.rs | 16 ++-- 23 files changed, 152 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c18ea3be..f3f51e73a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ dependencies = [ "log", "pin-project-lite", "serde", - "strum", + "strum 0.25.0", "thiserror", "tokio", "tower", @@ -303,23 +303,23 @@ dependencies = [ [[package]] name = "async-graphql" -version = "6.0.11" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298a5d587d6e6fdb271bf56af2dc325a80eb291fd0fc979146584b9a05494a8c" +checksum = "bf338d20ba5bab309f55ce8df95d65ee19446f7737f06f4a64593ab2c6b546ad" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", "async-stream", "async-trait", - "base64 0.13.1", + "base64 0.22.1", "bytes", "chrono", "fast_chemail", "fnv", "futures-util", "handlebars", - "http 0.2.12", + "http 1.1.0", "indexmap 2.2.6", "mime", "multer", @@ -330,7 +330,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "static_assertions", + "static_assertions_next", "tempfile", "thiserror", "tracing", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "async-graphql-derive" -version = "6.0.11" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f329c7eb9b646a72f70c9c4b516c70867d356ec46cb00dcac8ad343fd006b0" +checksum = "fc51fd6b7102acda72bc94e8ae1543844d5688ff394a6cf7c21f2a07fe2d64e4" dependencies = [ "Inflector", "async-graphql-parser", @@ -350,16 +350,16 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "strum", + "strum 0.26.3", "syn 2.0.68", "thiserror", ] [[package]] name = "async-graphql-parser" -version = "6.0.11" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6139181845757fd6a73fbb8839f3d036d7150b798db0e9bb3c6e83cdd65bd53b" +checksum = "75361eefd64e39f89bead4cb45fddbaf60ddb0e7b15fb7c852b6088bcd63071f" dependencies = [ "async-graphql-value", "pest", @@ -369,9 +369,9 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "6.0.11" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323a5143f5bdd2030f45e3f2e0c821c9b1d36e79cf382129c64299c50a7f3750" +checksum = "c1f665d2d52b41c4ed1f01c43f3ef27a2fe0af2452ed5c8bc7ac9b1a8719afaa" dependencies = [ "bytes", "indexmap 2.2.6", @@ -707,12 +707,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -2158,9 +2152,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.5.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" +checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" dependencies = [ "log", "pest", @@ -3360,6 +3354,7 @@ dependencies = [ "psl", "rand", "rand_chacha", + "rustls 0.23.10", "sentry", "serde", "serde_json", @@ -3909,16 +3904,15 @@ checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] name = "multer" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.12", + "http 1.1.0", "httparse", - "log", "memchr", "mime", "spin", @@ -4732,11 +4726,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "once_cell", "toml_edit", ] @@ -6045,10 +6038,10 @@ dependencies = [ ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "static_assertions_next" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" [[package]] name = "stringprep" @@ -6073,7 +6066,16 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros", + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", ] [[package]] @@ -6089,6 +6091,19 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.68", +] + [[package]] name = "subtle" version = "2.6.1" @@ -6361,9 +6376,9 @@ checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.6", "toml_datetime", diff --git a/Cargo.toml b/Cargo.toml index b002bed1d..3e5f52c13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ oauth2-types = { path = "./crates/oauth2-types/", version = "=0.9.0" } # GraphQL server [workspace.dependencies.async-graphql] -version = "6.0.11" +version = "7.0.6" features = ["chrono", "url", "tracing"] # Utility to write and implement async traits diff --git a/crates/axum-utils/src/client_authorization.rs b/crates/axum-utils/src/client_authorization.rs index d716b0dc9..d4217430c 100644 --- a/crates/axum-utils/src/client_authorization.rs +++ b/crates/axum-utils/src/client_authorization.rs @@ -489,7 +489,7 @@ where #[cfg(test)] mod tests { - use axum::body::{Bytes, Full}; + use axum::body::Body; use http::{Method, Request}; use super::*; @@ -502,7 +502,7 @@ mod tests { http::header::CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref(), ) - .body(Full::::new("client_id=client-id&foo=bar".into())) + .body(Body::new("client_id=client-id&foo=bar".to_owned())) .unwrap(); assert_eq!( @@ -530,7 +530,7 @@ mod tests { http::header::AUTHORIZATION, "Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ=", ) - .body(Full::::new("foo=bar".into())) + .body(Body::new("foo=bar".to_owned())) .unwrap(); assert_eq!( @@ -557,7 +557,7 @@ mod tests { http::header::AUTHORIZATION, "Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ=", ) - .body(Full::::new("client_id=client-id&foo=bar".into())) + .body(Body::new("client_id=client-id&foo=bar".to_owned())) .unwrap(); assert_eq!( @@ -584,7 +584,7 @@ mod tests { http::header::AUTHORIZATION, "Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ=", ) - .body(Full::::new("client_id=mismatch-id&foo=bar".into())) + .body(Body::new("client_id=mismatch-id&foo=bar".to_owned())) .unwrap(); assert!(matches!( @@ -600,7 +600,7 @@ mod tests { mime::APPLICATION_WWW_FORM_URLENCODED.as_ref(), ) .header(http::header::AUTHORIZATION, "Basic invalid") - .body(Full::::new("foo=bar".into())) + .body(Body::new("foo=bar".to_owned())) .unwrap(); assert!(matches!( @@ -617,8 +617,8 @@ mod tests { http::header::CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref(), ) - .body(Full::::new( - "client_id=client-id&client_secret=client-secret&foo=bar".into(), + .body(Body::new( + "client_id=client-id&client_secret=client-secret&foo=bar".to_owned(), )) .unwrap(); @@ -640,7 +640,7 @@ mod tests { async fn client_assertion_test() { // Signed with client_secret = "client-secret" let jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnQtaWQiLCJzdWIiOiJjbGllbnQtaWQiLCJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tL29hdXRoMi9pbnRyb3NwZWN0IiwianRpIjoiYWFiYmNjIiwiZXhwIjoxNTE2MjM5MzIyLCJpYXQiOjE1MTYyMzkwMjJ9.XTaACG_Rww0GPecSZvkbem-AczNy9LLNBueCLCiQajU"; - let body = Bytes::from(format!( + let body = Body::new(format!( "client_assertion_type={JWT_BEARER_CLIENT_ASSERTION}&client_assertion={jwt}&foo=bar", )); @@ -650,7 +650,7 @@ mod tests { http::header::CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref(), ) - .body(Full::new(body)) + .body(body) .unwrap(); let authz = ClientAuthorization::::from_request(req, &()) diff --git a/crates/handlers/Cargo.toml b/crates/handlers/Cargo.toml index 98b2c7281..398ff9ddb 100644 --- a/crates/handlers/Cargo.toml +++ b/crates/handlers/Cargo.toml @@ -34,6 +34,7 @@ tower-http.workspace = true axum.workspace = true axum-macros = "0.4.1" axum-extra.workspace = true +rustls.workspace = true async-graphql.workspace = true diff --git a/crates/handlers/src/compat/login.rs b/crates/handlers/src/compat/login.rs index f7766a419..749314ee4 100644 --- a/crates/handlers/src/compat/login.rs +++ b/crates/handlers/src/compat/login.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::{extract::State, response::IntoResponse, Json, TypedHeader}; +use axum::{extract::State, response::IntoResponse, Json}; +use axum_extra::typed_header::TypedHeader; use chrono::Duration; use hyper::StatusCode; use mas_axum_utils::sentry::SentryEventID; @@ -433,12 +434,12 @@ mod tests { use sqlx::PgPool; use super::*; - use crate::test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}; + use crate::test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}; /// Test that the server advertises the right login flows. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_get_login(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Now let's get the login flows @@ -470,7 +471,7 @@ mod tests { /// manager is disabled #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_password_disabled(pool: PgPool) { - init_tracing(); + setup(); let state = { let mut state = TestState::from_pool(pool).await.unwrap(); state.password_manager = PasswordManager::disabled(); @@ -518,7 +519,7 @@ mod tests { /// compatibility API. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_user_password_login(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Let's provision a user and add a password to it. This part is hard to test @@ -633,7 +634,7 @@ mod tests { /// Test the response of an unsupported login flow. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_unsupported_login(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Try to login with an unsupported login flow. @@ -650,7 +651,7 @@ mod tests { /// Test `m.login.token` login flow. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_login_token_login(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a user diff --git a/crates/handlers/src/compat/logout.rs b/crates/handlers/src/compat/logout.rs index f74fe45e8..55fb20664 100644 --- a/crates/handlers/src/compat/logout.rs +++ b/crates/handlers/src/compat/logout.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::{response::IntoResponse, Json, TypedHeader}; +use axum::{response::IntoResponse, Json}; +use axum_extra::typed_header::TypedHeader; use headers::{authorization::Bearer, Authorization}; use hyper::StatusCode; use mas_axum_utils::sentry::SentryEventID; diff --git a/crates/handlers/src/graphql/mod.rs b/crates/handlers/src/graphql/mod.rs index 1ea288080..12dbfebe7 100644 --- a/crates/handlers/src/graphql/mod.rs +++ b/crates/handlers/src/graphql/mod.rs @@ -23,11 +23,13 @@ use async_graphql::{ }; use axum::{ async_trait, - extract::{BodyStream, RawQuery, State as AxumState}, + body::Body, + extract::{RawQuery, State as AxumState}, http::StatusCode, response::{Html, IntoResponse, Response}, - Json, TypedHeader, + Json, }; +use axum_extra::typed_header::TypedHeader; use futures_util::TryStreamExt; use headers::{authorization::Bearer, Authorization, ContentType, HeaderValue}; use hyper::header::CACHE_CONTROL; @@ -286,8 +288,9 @@ pub async fn post( cookie_jar: CookieJar, content_type: Option>, authorization: Option>>, - body: BodyStream, + body: Body, ) -> Result { + let body = body.into_data_stream(); let token = authorization .as_ref() .map(|TypedHeader(Authorization(bearer))| bearer.token()); diff --git a/crates/handlers/src/graphql/tests.rs b/crates/handlers/src/graphql/tests.rs index 64a3db4c1..463abb61d 100644 --- a/crates/handlers/src/graphql/tests.rs +++ b/crates/handlers/src/graphql/tests.rs @@ -29,7 +29,7 @@ use sqlx::PgPool; use crate::{ test_utils, - test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}, + test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}, }; async fn create_test_client(state: &TestState) -> Client { @@ -131,7 +131,7 @@ struct GraphQLResponse { /// Test that the GraphQL endpoint can be queried with a GET request. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_get(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let request = Request::get("/graphql?query={viewer{__typename}}").empty(); @@ -155,7 +155,7 @@ async fn test_get(pool: PgPool) { /// anonymously. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_anonymous_viewer(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let req = Request::post("/graphql").json(serde_json::json!({ @@ -186,7 +186,7 @@ async fn test_anonymous_viewer(pool: PgPool) { /// Test that the GraphQL endpoint can be authenticated with a bearer token. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_oauth2_viewer(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Start by creating a user, a client and a token @@ -203,7 +203,7 @@ async fn test_oauth2_viewer(pool: PgPool) { query { viewer { __typename - + ... on User { id username @@ -233,7 +233,7 @@ async fn test_oauth2_viewer(pool: PgPool) { /// Test that the GraphQL endpoint requires the GraphQL scope. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_oauth2_no_scope(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Start by creating a user, a client and a token @@ -271,7 +271,7 @@ async fn test_oauth2_no_scope(pool: PgPool) { /// Test the admin scope on the GraphQL endpoint. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_oauth2_admin(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Start by creating a user, a client and two tokens @@ -301,7 +301,7 @@ async fn test_oauth2_admin(pool: PgPool) { username } } - ", + ", "variables": { "id": format!("user:{id}", id = user2.id), }, @@ -331,7 +331,7 @@ async fn test_oauth2_admin(pool: PgPool) { username } } - ", + ", "variables": { "id": format!("user:{id}", id = user2.id), }, @@ -358,7 +358,7 @@ async fn test_oauth2_admin(pool: PgPool) { /// client_credentials grant. #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_oauth2_client_credentials(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client @@ -397,7 +397,7 @@ async fn test_oauth2_client_credentials(pool: PgPool) { viewer { __typename } - + viewerSession { __typename } @@ -464,7 +464,7 @@ async fn test_oauth2_client_credentials(pool: PgPool) { viewer { __typename } - + viewerSession { __typename } @@ -572,7 +572,7 @@ async fn test_oauth2_client_credentials(pool: PgPool) { /// Test the addUser mutation #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_add_user(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client diff --git a/crates/handlers/src/lib.rs b/crates/handlers/src/lib.rs index 51f3185e1..bc7def815 100644 --- a/crates/handlers/src/lib.rs +++ b/crates/handlers/src/lib.rs @@ -26,11 +26,10 @@ use std::{convert::Infallible, time::Duration}; use axum::{ - body::{Bytes, HttpBody}, extract::{FromRef, FromRequestParts, OriginalUri, RawQuery, State}, http::Method, response::{Html, IntoResponse}, - routing::{get, on, post, MethodFilter}, + routing::{get, post}, Router, }; use headers::HeaderName; @@ -97,20 +96,16 @@ pub use self::{ upstream_oauth2::cache::MetadataCache, }; -pub fn healthcheck_router() -> Router +pub fn healthcheck_router() -> Router where - B: HttpBody + Send + 'static, S: Clone + Send + Sync + 'static, PgPool: FromRef, { Router::new().route(mas_router::Healthcheck::route(), get(self::health::get)) } -pub fn graphql_router(playground: bool) -> Router +pub fn graphql_router(playground: bool) -> Router where - B: HttpBody + Send + 'static, - ::Data: Into, - ::Error: std::error::Error + Send + Sync, S: Clone + Send + Sync + 'static, graphql::Schema: FromRef, BoundActivityTracker: FromRequestParts, @@ -147,9 +142,8 @@ where router } -pub fn discovery_router() -> Router +pub fn discovery_router() -> Router where - B: HttpBody + Send + 'static, S: Clone + Send + Sync + 'static, Keystore: FromRef, SiteConfig: FromRef, @@ -181,11 +175,8 @@ where ) } -pub fn api_router() -> Router +pub fn api_router() -> Router where - B: HttpBody + Send + 'static, - ::Data: Send, - ::Error: std::error::Error + Send + Sync, S: Clone + Send + Sync + 'static, Keystore: FromRef, UrlBuilder: FromRef, @@ -207,10 +198,7 @@ where ) .route( mas_router::OidcUserinfo::route(), - on( - MethodFilter::POST | MethodFilter::GET, - self::oauth2::userinfo::get, - ), + get(self::oauth2::userinfo::get).post(self::oauth2::userinfo::get), ) .route( mas_router::OAuth2Introspection::route(), @@ -248,11 +236,8 @@ where } #[allow(clippy::trait_duplication_in_bounds)] -pub fn compat_router() -> Router +pub fn compat_router() -> Router where - B: HttpBody + Send + 'static, - ::Data: Send, - ::Error: std::error::Error + Send + Sync, S: Clone + Send + Sync + 'static, UrlBuilder: FromRef, SiteConfig: FromRef, @@ -305,11 +290,8 @@ where } #[allow(clippy::too_many_lines)] -pub fn human_router(templates: Templates) -> Router +pub fn human_router(templates: Templates) -> Router where - B: HttpBody + Send + 'static, - ::Data: Send, - ::Error: std::error::Error + Send + Sync, S: Clone + Send + Sync + 'static, UrlBuilder: FromRef, PreferredLanguage: FromRequestParts, diff --git a/crates/handlers/src/oauth2/device/authorize.rs b/crates/handlers/src/oauth2/device/authorize.rs index 4cc9ed8b1..594253910 100644 --- a/crates/handlers/src/oauth2/device/authorize.rs +++ b/crates/handlers/src/oauth2/device/authorize.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::{extract::State, response::IntoResponse, Json, TypedHeader}; +use axum::{extract::State, response::IntoResponse, Json}; +use axum_extra::typed_header::TypedHeader; use chrono::Duration; use headers::{CacheControl, Pragma}; use hyper::StatusCode; @@ -177,11 +178,11 @@ mod tests { }; use sqlx::PgPool; - use crate::test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}; + use crate::test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_device_code_request(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client diff --git a/crates/handlers/src/oauth2/discovery.rs b/crates/handlers/src/oauth2/discovery.rs index d1e09aaf4..80a543284 100644 --- a/crates/handlers/src/oauth2/discovery.rs +++ b/crates/handlers/src/oauth2/discovery.rs @@ -206,11 +206,11 @@ mod tests { use oauth2_types::oidc::ProviderMetadata; use sqlx::PgPool; - use crate::test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}; + use crate::test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_valid_discovery_metadata(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let request = Request::get("/.well-known/openid-configuration").empty(); diff --git a/crates/handlers/src/oauth2/introspection.rs b/crates/handlers/src/oauth2/introspection.rs index cec375068..44eff0cdc 100644 --- a/crates/handlers/src/oauth2/introspection.rs +++ b/crates/handlers/src/oauth2/introspection.rs @@ -474,12 +474,12 @@ mod tests { use crate::{ oauth2::generate_token_pair, - test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}, + test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}, }; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_introspect_oauth_tokens(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client which will be used to do introspection requests @@ -678,7 +678,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_introspect_compat_tokens(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client which will be used to do introspection requests diff --git a/crates/handlers/src/oauth2/registration.rs b/crates/handlers/src/oauth2/registration.rs index 5b493b144..5600f7a26 100644 --- a/crates/handlers/src/oauth2/registration.rs +++ b/crates/handlers/src/oauth2/registration.rs @@ -317,7 +317,7 @@ mod tests { use crate::{ oauth2::registration::host_is_public_suffix, - test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}, + test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}, }; #[test] @@ -342,7 +342,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_registration_error(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Body is not a JSON @@ -439,7 +439,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_registration(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // A successful registration with no authentication should not return a client diff --git a/crates/handlers/src/oauth2/revoke.rs b/crates/handlers/src/oauth2/revoke.rs index 9e2d4c79a..ff725df32 100644 --- a/crates/handlers/src/oauth2/revoke.rs +++ b/crates/handlers/src/oauth2/revoke.rs @@ -258,12 +258,12 @@ mod tests { use super::*; use crate::{ oauth2::generate_token_pair, - test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}, + test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}, }; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_revoke_access_token(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let request = diff --git a/crates/handlers/src/oauth2/token.rs b/crates/handlers/src/oauth2/token.rs index a11aab359..79e95a4b8 100644 --- a/crates/handlers/src/oauth2/token.rs +++ b/crates/handlers/src/oauth2/token.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use axum::{extract::State, response::IntoResponse, Json, TypedHeader}; +use axum::{extract::State, response::IntoResponse, Json}; +use axum_extra::typed_header::TypedHeader; use chrono::Duration; use headers::{CacheControl, HeaderMap, HeaderMapExt, Pragma}; use hyper::StatusCode; @@ -781,11 +782,11 @@ mod tests { use sqlx::PgPool; use super::*; - use crate::test_utils::{init_tracing, RequestBuilderExt, ResponseExt, TestState}; + use crate::test_utils::{setup, RequestBuilderExt, ResponseExt, TestState}; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_auth_code_grant(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client @@ -995,7 +996,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_refresh_token_grant(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client @@ -1118,7 +1119,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_client_credentials(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client @@ -1245,7 +1246,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_device_code_grant(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client @@ -1431,7 +1432,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_unsupported_grant(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); // Provision a client diff --git a/crates/handlers/src/oauth2/webfinger.rs b/crates/handlers/src/oauth2/webfinger.rs index 7f925d15f..4904442cb 100644 --- a/crates/handlers/src/oauth2/webfinger.rs +++ b/crates/handlers/src/oauth2/webfinger.rs @@ -15,8 +15,9 @@ use axum::{ extract::{Query, State}, response::IntoResponse, - Json, TypedHeader, + Json, }; +use axum_extra::typed_header::TypedHeader; use headers::ContentType; use mas_router::UrlBuilder; use oauth2_types::webfinger::WebFingerResponse; diff --git a/crates/handlers/src/preferred_language.rs b/crates/handlers/src/preferred_language.rs index 0e21b1fc4..1ec12495d 100644 --- a/crates/handlers/src/preferred_language.rs +++ b/crates/handlers/src/preferred_language.rs @@ -18,8 +18,8 @@ use axum::{ async_trait, extract::{FromRef, FromRequestParts}, http::request::Parts, - TypedHeader, }; +use axum_extra::typed_header::TypedHeader; use mas_axum_utils::language_detection::AcceptLanguage; use mas_i18n::{locale, DataLocale, Translator}; diff --git a/crates/handlers/src/test_utils.rs b/crates/handlers/src/test_utils.rs index 7ddc1f7e5..cdead2bb3 100644 --- a/crates/handlers/src/test_utils.rs +++ b/crates/handlers/src/test_utils.rs @@ -60,10 +60,11 @@ use crate::{ ActivityTracker, BoundActivityTracker, }; -// This might fail if it's not the first time it's being called, which is fine, -// so we ignore the result +/// Setup rustcrypto and tracing for tests. #[allow(unused_must_use)] -pub(crate) fn init_tracing() { +pub(crate) fn setup() { + rustls::crypto::aws_lc_rs::default_provider().install_default(); + tracing_subscriber::fmt() .with_max_level(tracing::Level::INFO) .with_test_writer() @@ -230,8 +231,7 @@ impl TestState { pub async fn request(&self, request: Request) -> Response where - B: HttpBody + Send + 'static, - ::Data: Into, + B: HttpBody + Send + 'static, ::Error: std::error::Error + Send + Sync, B::Error: std::error::Error + Send + Sync, B::Data: Send, @@ -242,7 +242,8 @@ impl TestState { .merge(crate::compat_router()) .merge(crate::human_router(self.templates.clone())) .merge(crate::graphql_router(false)) - .with_state(self.clone()); + .with_state(self.clone()) + .into_service(); // Both unwrap are on Infallible, so this is safe let response = app @@ -256,7 +257,7 @@ impl TestState { let (parts, body) = response.into_parts(); // This could actually fail, but do we really care about that? - let body = hyper::body::to_bytes(body) + let body = axum::body::to_bytes(body, usize::MAX) .await .expect("Failed to read response body"); let body = std::str::from_utf8(&body) diff --git a/crates/handlers/src/upstream_oauth2/cache.rs b/crates/handlers/src/upstream_oauth2/cache.rs index cd04260d1..67e547915 100644 --- a/crates/handlers/src/upstream_oauth2/cache.rs +++ b/crates/handlers/src/upstream_oauth2/cache.rs @@ -293,11 +293,11 @@ mod tests { use ulid::Ulid; use super::*; - use crate::test_utils::init_tracing; + use crate::test_utils::setup; #[tokio::test] async fn test_metadata_cache() { - init_tracing(); + setup(); let calls = Arc::new(AtomicUsize::new(0)); let closure_calls = Arc::clone(&calls); let handler = move |req: Request| { @@ -418,7 +418,7 @@ mod tests { #[tokio::test] async fn test_lazy_provider_infos() { - init_tracing(); + setup(); let calls = Arc::new(AtomicUsize::new(0)); let closure_calls = Arc::clone(&calls); let handler = move |req: Request| { diff --git a/crates/handlers/src/upstream_oauth2/link.rs b/crates/handlers/src/upstream_oauth2/link.rs index c51c89a37..34f100f83 100644 --- a/crates/handlers/src/upstream_oauth2/link.rs +++ b/crates/handlers/src/upstream_oauth2/link.rs @@ -15,8 +15,9 @@ use axum::{ extract::{Path, State}, response::{Html, IntoResponse, Response}, - Form, TypedHeader, + Form, }; +use axum_extra::typed_header::TypedHeader; use hyper::StatusCode; use mas_axum_utils::{ cookies::CookieJar, @@ -859,13 +860,11 @@ mod tests { use sqlx::PgPool; use super::UpstreamSessionsCookie; - use crate::test_utils::{ - init_tracing, CookieHelper, RequestBuilderExt, ResponseExt, TestState, - }; + use crate::test_utils::{setup, CookieHelper, RequestBuilderExt, ResponseExt, TestState}; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let mut rng = state.rng(); let cookies = CookieHelper::new(); diff --git a/crates/handlers/src/views/login.rs b/crates/handlers/src/views/login.rs index a626a53cd..177253d78 100644 --- a/crates/handlers/src/views/login.rs +++ b/crates/handlers/src/views/login.rs @@ -15,8 +15,8 @@ use axum::{ extract::{Form, Query, State}, response::{Html, IntoResponse, Response}, - TypedHeader, }; +use axum_extra::typed_header::TypedHeader; use hyper::StatusCode; use mas_axum_utils::{ cookies::CookieJar, @@ -319,14 +319,14 @@ mod test { use crate::{ test_utils::{ - init_tracing, test_site_config, CookieHelper, RequestBuilderExt, ResponseExt, TestState, + setup, test_site_config, CookieHelper, RequestBuilderExt, ResponseExt, TestState, }, SiteConfig, }; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_password_disabled(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool_with_site_config( pool, SiteConfig { @@ -431,7 +431,7 @@ mod test { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_password_login(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let mut rng = state.rng(); let cookies = CookieHelper::new(); diff --git a/crates/handlers/src/views/recovery/start.rs b/crates/handlers/src/views/recovery/start.rs index c8324042c..06091b997 100644 --- a/crates/handlers/src/views/recovery/start.rs +++ b/crates/handlers/src/views/recovery/start.rs @@ -17,8 +17,9 @@ use std::str::FromStr; use axum::{ extract::State, response::{Html, IntoResponse, Response}, - Form, TypedHeader, + Form, }; +use axum_extra::typed_header::TypedHeader; use lettre::Address; use mas_axum_utils::{ cookies::CookieJar, diff --git a/crates/handlers/src/views/register.rs b/crates/handlers/src/views/register.rs index 12371d805..67cb9425f 100644 --- a/crates/handlers/src/views/register.rs +++ b/crates/handlers/src/views/register.rs @@ -17,8 +17,8 @@ use std::str::FromStr; use axum::{ extract::{Form, Query, State}, response::{Html, IntoResponse, Response}, - TypedHeader, }; +use axum_extra::typed_header::TypedHeader; use hyper::StatusCode; use lettre::Address; use mas_axum_utils::{ @@ -335,14 +335,14 @@ mod tests { use crate::{ test_utils::{ - init_tracing, test_site_config, CookieHelper, RequestBuilderExt, ResponseExt, TestState, + setup, test_site_config, CookieHelper, RequestBuilderExt, ResponseExt, TestState, }, SiteConfig, }; #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_password_disabled(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool_with_site_config( pool, SiteConfig { @@ -375,7 +375,7 @@ mod tests { /// Test the registration happy path #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let cookies = CookieHelper::new(); @@ -425,7 +425,7 @@ mod tests { /// When the two password fields mismatch, it should give an error #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register_password_mismatch(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let cookies = CookieHelper::new(); @@ -466,7 +466,7 @@ mod tests { #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register_username_too_short(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let cookies = CookieHelper::new(); @@ -508,7 +508,7 @@ mod tests { /// When the user already exists in the database, it should give an error #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register_user_exists(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let mut rng = state.rng(); let cookies = CookieHelper::new(); @@ -560,7 +560,7 @@ mod tests { /// an error #[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")] async fn test_register_user_reserved(pool: PgPool) { - init_tracing(); + setup(); let state = TestState::from_pool(pool).await.unwrap(); let cookies = CookieHelper::new(); From 487e034184c9a7aab49955ff4aab241f1a068f36 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 12:04:45 +0200 Subject: [PATCH 09/16] mas-iana-codegen: use rustls not the native TLS stack --- Cargo.lock | 176 ++++++++++----------------------- crates/iana-codegen/Cargo.toml | 4 +- 2 files changed, 56 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3f51e73a..518d3c09f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1854,21 +1854,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2439,22 +2424,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.4.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots 0.26.3", ] [[package]] @@ -3919,23 +3889,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nom" version = "7.1.3" @@ -4107,50 +4060,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry" version = "0.23.0" @@ -4833,6 +4748,53 @@ dependencies = [ "psl-types", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.10", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.10", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2 0.5.7", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -4990,38 +4952,37 @@ checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "http-body-util", "hyper 1.4.0", "hyper-rustls", - "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.10", "rustls-pemfile 2.1.2", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", - "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 0.26.3", "winreg", ] @@ -6155,27 +6116,6 @@ dependencies = [ "syn 2.0.68", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "target-lexicon" version = "0.12.14" @@ -6310,16 +6250,6 @@ dependencies = [ "syn 2.0.68", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" diff --git a/crates/iana-codegen/Cargo.toml b/crates/iana-codegen/Cargo.toml index d5da9ebaf..fb1995e87 100644 --- a/crates/iana-codegen/Cargo.toml +++ b/crates/iana-codegen/Cargo.toml @@ -18,7 +18,9 @@ camino.workspace = true convert_case = "0.6.0" csv = "1.3.0" futures-util = "0.3.30" -reqwest = "0.12.5" +reqwest = { version = "0.12.5", default-features = false, features = [ + "rustls-tls", +] } serde.workspace = true tokio.workspace = true tracing.workspace = true From 9032d751ad3ae3dc172524eb9eaa391361d35dae Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 14:13:49 +0200 Subject: [PATCH 10/16] Write an adapter for opentelemetry-http --- Cargo.lock | 3 ++ crates/cli/src/telemetry.rs | 11 +++--- crates/http/Cargo.toml | 7 ++++ crates/http/src/client.rs | 76 +++++++++++++++++++++++++++++++++++++ crates/http/src/lib.rs | 4 +- 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 518d3c09f..ef34d05ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3348,9 +3348,11 @@ name = "mas-http" version = "0.9.0" dependencies = [ "anyhow", + "async-trait", "bytes", "futures-util", "headers", + "http 0.2.12", "http 1.1.0", "http-body 1.0.0", "http-body-util", @@ -3359,6 +3361,7 @@ dependencies = [ "hyper-util", "mas-tower", "opentelemetry", + "opentelemetry-http", "opentelemetry-semantic-conventions", "pin-project-lite", "rustls 0.23.10", diff --git a/crates/cli/src/telemetry.rs b/crates/cli/src/telemetry.rs index 48b4ecab6..5f54dc54c 100644 --- a/crates/cli/src/telemetry.rs +++ b/crates/cli/src/telemetry.rs @@ -15,11 +15,12 @@ use std::time::Duration; use anyhow::Context as _; -use hyper::{header::CONTENT_TYPE, Body, Response}; +use hyper::{header::CONTENT_TYPE, Response}; use mas_config::{ MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig, TracingExporterKind, }; +use mas_http::OtelClient; use opentelemetry::{ global, propagation::{TextMapCompositePropagator, TextMapPropagator}, @@ -87,7 +88,7 @@ fn propagator(propagators: &[Propagator]) -> impl TextMapPropagator { fn http_client() -> impl opentelemetry_http::HttpClient + 'static { let client = mas_http::make_untraced_client(); - opentelemetry_http::hyper::HyperClient::new_with_timeout(client, Duration::from_secs(30)) + OtelClient::new(client) } fn stdout_tracer_provider() -> TracerProvider { @@ -161,14 +162,14 @@ fn stdout_metric_reader() -> PeriodicReader { PeriodicReader::builder(exporter, opentelemetry_sdk::runtime::Tokio).build() } -type PromServiceFuture = std::future::Ready, std::convert::Infallible>>; +type PromServiceFuture = std::future::Ready, std::convert::Infallible>>; #[allow(clippy::needless_pass_by_value)] fn prometheus_service_fn(_req: T) -> PromServiceFuture { use prometheus::{Encoder, TextEncoder}; let response = if let Some(registry) = PROMETHEUS_REGISTRY.get() { - let mut buffer = vec![]; + let mut buffer = String::new(); let encoder = TextEncoder::new(); let metric_families = registry.gather(); @@ -178,7 +179,7 @@ fn prometheus_service_fn(_req: T) -> PromServiceFuture { Response::builder() .status(200) .header(CONTENT_TYPE, encoder.format_type()) - .body(Body::from(buffer)) + .body(buffer) .unwrap() } else { Response::builder() diff --git a/crates/http/Cargo.toml b/crates/http/Cargo.toml index 2d336d3bf..c47b08d6b 100644 --- a/crates/http/Cargo.toml +++ b/crates/http/Cargo.toml @@ -12,6 +12,7 @@ repository.workspace = true workspace = true [dependencies] +async-trait.workspace = true bytes = "1.6.0" futures-util = "0.3.30" headers.workspace = true @@ -22,6 +23,7 @@ hyper.workspace = true hyper-util.workspace = true hyper-rustls = { workspace = true, optional = true } opentelemetry.workspace = true +opentelemetry-http = { workspace = true, optional = true } opentelemetry-semantic-conventions.workspace = true rustls = { workspace = true, optional = true } rustls-platform-verifier = { workspace = true, optional = true } @@ -35,6 +37,9 @@ tower-http.workspace = true tracing.workspace = true tracing-opentelemetry.workspace = true +# opentelemetry-http still requires http 0.2, and we need to convert types +http02 = { package = "http", version = "0.2.12", optional = true } + mas-tower = { workspace = true, optional = true } [dev-dependencies] @@ -47,6 +52,8 @@ client = [ "dep:rustls", "dep:hyper-rustls", "dep:rustls-platform-verifier", + "dep:http02", + "dep:opentelemetry-http", "tower/limit", "tower-http/timeout", "tower-http/follow-redirect", diff --git a/crates/http/src/client.rs b/crates/http/src/client.rs index f227e35c0..1449778f3 100644 --- a/crates/http/src/client.rs +++ b/crates/http/src/client.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use bytes::Bytes; +use http_body_util::{BodyExt, Full}; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; pub use hyper_util::client::legacy::Client; use hyper_util::{ @@ -25,6 +27,7 @@ use mas_tower::{ DurationRecorderLayer, DurationRecorderService, FnWrapper, InFlightCounterLayer, InFlightCounterService, TraceLayer, TraceService, }; +use opentelemetry_http::HttpClient; use opentelemetry_semantic_conventions::trace::SERVER_ADDRESS; use tower::Layer; use tracing::Span; @@ -94,3 +97,76 @@ fn make_connector( .enable_http2() .wrap_connector(http) } + +/// A client which can be used by opentelemetry-http to send request through +/// hyper 1.x +/// +/// This is needed until OTEL upgrades to hyper 1.x +/// +#[derive(Debug)] +pub struct OtelClient { + client: UntracedClient>, +} + +impl OtelClient { + /// Create a new [`OtelClient`] from a [`UntracedClient`] + #[must_use] + pub fn new(client: UntracedClient>) -> Self { + Self { client } + } +} + +#[async_trait::async_trait] +impl HttpClient for OtelClient { + async fn send( + &self, + request: opentelemetry_http::Request>, + ) -> Result, opentelemetry_http::HttpError> { + // This is the annoying part: converting the OTEL http0.2 request to a http1 + // request + let (parts, body) = request.into_parts(); + let body = Full::new(Bytes::from(body)); + let mut request = http::Request::new(body); + + *request.uri_mut() = parts.uri.to_string().parse().unwrap(); + *request.method_mut() = match parts.method { + http02::Method::GET => http::Method::GET, + http02::Method::POST => http::Method::POST, + http02::Method::PUT => http::Method::PUT, + http02::Method::DELETE => http::Method::DELETE, + http02::Method::HEAD => http::Method::HEAD, + http02::Method::OPTIONS => http::Method::OPTIONS, + http02::Method::CONNECT => http::Method::CONNECT, + http02::Method::PATCH => http::Method::PATCH, + http02::Method::TRACE => http::Method::TRACE, + _ => return Err(opentelemetry_http::HttpError::from("Unsupported method")), + }; + request + .headers_mut() + .extend(parts.headers.into_iter().map(|(k, v)| { + ( + k.map(|k| http::HeaderName::from_bytes(k.as_ref()).unwrap()), + http::HeaderValue::from_bytes(v.as_ref()).unwrap(), + ) + })); + + // Send the request + let response = self.client.request(request).await?; + + // Convert back the response + let (parts, body) = response.into_parts(); + let body = body.collect().await?.to_bytes(); + let mut response = opentelemetry_http::Response::new(body); + *response.status_mut() = parts.status.as_u16().try_into().unwrap(); + response + .headers_mut() + .extend(parts.headers.into_iter().map(|(k, v)| { + ( + k.map(|k| http02::HeaderName::from_bytes(k.as_ref()).unwrap()), + http02::HeaderValue::from_bytes(v.as_ref()).unwrap(), + ) + })); + + Ok(response) + } +} diff --git a/crates/http/src/lib.rs b/crates/http/src/lib.rs index 48b7f801c..3541ca4fc 100644 --- a/crates/http/src/lib.rs +++ b/crates/http/src/lib.rs @@ -26,8 +26,8 @@ mod service; #[cfg(feature = "client")] pub use self::{ client::{ - make_traced_connector, make_untraced_client, Client, TracedClient, TracedConnector, - UntracedClient, UntracedConnector, + make_traced_connector, make_untraced_client, Client, OtelClient, TracedClient, + TracedConnector, UntracedClient, UntracedConnector, }, layers::client::{ClientLayer, ClientService}, }; From 4255d725ed00d60bc73a40852e9339e5d3ce1333 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 14:18:13 +0200 Subject: [PATCH 11/16] Move Sentry to the workspace dependencies and upgrade --- Cargo.lock | 55 +++++++++++++----------------------- Cargo.toml | 15 ++++++++++ crates/axum-utils/Cargo.toml | 2 +- crates/cli/Cargo.toml | 6 ++-- crates/handlers/Cargo.toml | 2 +- 5 files changed, 39 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef34d05ab..bdc5e8553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2268,17 +2268,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "hostname" version = "0.4.0" @@ -2999,7 +2988,7 @@ dependencies = [ "fastrand 2.1.0", "futures-io", "futures-util", - "hostname 0.4.0", + "hostname", "httpdate", "idna 0.5.0", "mime", @@ -3753,12 +3742,6 @@ dependencies = [ "tracing-opentelemetry", ] -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -5401,9 +5384,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "sentry" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5" +checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066" dependencies = [ "sentry-backtrace", "sentry-contexts", @@ -5415,9 +5398,9 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cc8d4e04a73de8f718dc703943666d03f25d3e9e4d0fb271ca0b8c76dfa00e" +checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a" dependencies = [ "backtrace", "once_cell", @@ -5427,11 +5410,11 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6436c1bad22cdeb02179ea8ef116ffc217797c028927def303bc593d9320c0d1" +checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" dependencies = [ - "hostname 0.3.1", + "hostname", "libc", "os_info", "rustc_version", @@ -5441,9 +5424,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901f761681f97db3db836ef9e094acdd8756c40215326c194201941947164ef1" +checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30" dependencies = [ "once_cell", "rand", @@ -5454,9 +5437,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fbf1c163f8b6a9d05912e1b272afa27c652e8b47ea60cb9a57ad5e481eea99" +checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63" dependencies = [ "sentry-backtrace", "sentry-core", @@ -5464,11 +5447,11 @@ dependencies = [ [[package]] name = "sentry-tower" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e782e369edac4adfc5bf528b27577270bc3e7023c388ebad9db08e1d56b30b" +checksum = "6c90802b38c899a2c9e557dff25ad186362eddf755d5f5244001b172dd03bead" dependencies = [ - "http 0.2.12", + "http 1.1.0", "pin-project", "sentry-core", "tower-layer", @@ -5478,9 +5461,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82eabcab0a047040befd44599a1da73d3adb228ff53b5ed9795ae04535577704" +checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec" dependencies = [ "sentry-backtrace", "sentry-core", @@ -5490,9 +5473,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.31.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da956cca56e0101998c8688bc65ce1a96f00673a0e58e663664023d4c7911e82" +checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f" dependencies = [ "debugid", "hex", diff --git a/Cargo.toml b/Cargo.toml index 3e5f52c13..ab668e0f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -172,6 +172,21 @@ version = "0.3.1" version = "0.8.21" features = ["url", "chrono", "preserve_order"] +# Sentry error tracking +[workspace.dependencies.sentry] +version = "0.34.0" +default-features = false +features = ["backtrace", "contexts", "panic", "tower"] + +# Sentry tower layer +[workspace.dependencies.sentry-tower] +version = "0.34.0" +features = ["http"] + +# Sentry tracing integration +[workspace.dependencies.sentry-tracing] +version = "0.34.0" + # Serialization and deserialization [workspace.dependencies.serde] version = "1.0.203" diff --git a/crates/axum-utils/Cargo.toml b/crates/axum-utils/Cargo.toml index 00384864c..781815a58 100644 --- a/crates/axum-utils/Cargo.toml +++ b/crates/axum-utils/Cargo.toml @@ -27,7 +27,7 @@ hyper-util.workspace = true icu_locid = "1.4.0" mime = "0.3.17" rand.workspace = true -sentry = { version = "0.31.8", default-features = false } +sentry.workspace = true serde.workspace = true serde_with = "3.8.2" serde_urlencoded = "0.7.1" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 14032a5da..2c257a0f4 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -51,9 +51,9 @@ opentelemetry-semantic-conventions.workspace = true opentelemetry-stdout = { version = "0.4.0", features = ["trace", "metrics"] } opentelemetry_sdk = { version = "0.23.0", features = ["trace", "metrics", "rt-tokio"] } prometheus = "0.13.4" -sentry = { version = "0.31.8", default-features = false, features = ["backtrace", "contexts", "panic", "tower"] } -sentry-tracing = "0.31.8" -sentry-tower = { version = "0.31.8", features = ["http"] } +sentry.workspace = true +sentry-tracing.workspace = true +sentry-tower.workspace = true mas-config.workspace = true mas-data-model.workspace = true diff --git a/crates/handlers/Cargo.toml b/crates/handlers/Cargo.toml index 398ff9ddb..e3977dc81 100644 --- a/crates/handlers/Cargo.toml +++ b/crates/handlers/Cargo.toml @@ -25,7 +25,7 @@ opentelemetry-semantic-conventions.workspace = true # Error management thiserror.workspace = true anyhow.workspace = true -sentry = { version = "0.31.8", default-features = false } +sentry.workspace = true # Web server hyper.workspace = true From 2230358520ce72cc7a8dbd3283109b800372e392 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 15:12:35 +0200 Subject: [PATCH 12/16] Fix mas-cli This does a few things: - move `bytes` to workspace dependencies - write an hyper-based transport for Sentry - ignore OTEL errors related to propagations - fix everything else in mas-cli --- Cargo.lock | 69 ++++++-------------------- Cargo.toml | 5 +- crates/axum-utils/Cargo.toml | 2 +- crates/cli/Cargo.toml | 4 ++ crates/cli/src/commands/debug.rs | 9 ++-- crates/cli/src/commands/doctor.rs | 12 ++--- crates/cli/src/main.rs | 7 +++ crates/cli/src/sentry_transport/mod.rs | 34 ++++++------- crates/cli/src/server.rs | 43 +++++++++------- crates/cli/src/telemetry.rs | 24 +++++++-- crates/http/Cargo.toml | 2 +- crates/listener/Cargo.toml | 2 +- crates/oidc-client/Cargo.toml | 2 +- 13 files changed, 104 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdc5e8553..0a9203c1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -608,7 +608,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.0", + "hyper", "hyper-util", "itoa", "matchit", @@ -2097,25 +2097,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.5" @@ -2353,30 +2334,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.14.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.7", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.4.0" @@ -2386,7 +2343,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", + "h2", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -2406,7 +2363,7 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.0", + "hyper", "hyper-util", "rustls 0.23.10", "rustls-pki-types", @@ -2427,7 +2384,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.4.0", + "hyper", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -3147,14 +3104,18 @@ version = "0.9.0" dependencies = [ "anyhow", "axum", + "bytes", "camino", "clap", "console", "dialoguer", "dotenvy", "figment", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "httpdate", - "hyper 1.4.0", + "hyper", "ipnetwork", "itertools 0.13.0", "listenfd", @@ -3286,7 +3247,7 @@ dependencies = [ "cookie_store", "futures-util", "headers", - "hyper 1.4.0", + "hyper", "insta", "lettre", "mas-axum-utils", @@ -3345,7 +3306,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.0", + "hyper", "hyper-rustls", "hyper-util", "mas-tower", @@ -3497,7 +3458,7 @@ dependencies = [ "event-listener 5.3.1", "futures-util", "http-body 1.0.0", - "hyper 1.4.0", + "hyper", "hyper-util", "libc", "pin-project-lite", @@ -4075,9 +4036,7 @@ dependencies = [ "async-trait", "bytes", "http 0.2.12", - "hyper 0.14.29", "opentelemetry", - "tokio", ] [[package]] @@ -4943,7 +4902,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.0", + "hyper", "hyper-rustls", "hyper-util", "ipnet", @@ -7285,7 +7244,7 @@ dependencies = [ "futures", "http 1.1.0", "http-body-util", - "hyper 1.4.0", + "hyper", "hyper-util", "log", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index ab668e0f6..dae4e6804 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,10 @@ version = "0.7.5" version = "0.9.3" features = ["cookie-private", "cookie-key-expansion", "typed-header"] +# Bytes +[workspace.dependencies.bytes] +version = "1.6.0" + # UTF-8 paths [workspace.dependencies.camino] version = "1.1.7" @@ -241,7 +245,6 @@ version = "0.23.0" features = ["trace", "metrics"] [workspace.dependencies.opentelemetry-http] version = "0.12.0" -features = ["hyper", "tokio"] [workspace.dependencies.opentelemetry-semantic-conventions] version = "0.15.0" [workspace.dependencies.tracing-opentelemetry] diff --git a/crates/axum-utils/Cargo.toml b/crates/axum-utils/Cargo.toml index 781815a58..e94202f1f 100644 --- a/crates/axum-utils/Cargo.toml +++ b/crates/axum-utils/Cargo.toml @@ -15,7 +15,7 @@ workspace = true async-trait.workspace = true axum.workspace = true axum-extra.workspace = true -bytes = "1.6.0" +bytes.workspace = true chrono.workspace = true data-encoding = "2.6.0" futures-util = "0.3.30" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 2c257a0f4..ae8cb510f 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] anyhow.workspace = true axum.workspace = true +bytes.workspace = true camino.workspace = true clap.workspace = true console = "0.15.8" @@ -21,6 +22,9 @@ dialoguer = { version = "0.11.0", features = ["fuzzy-select"] } dotenvy = "0.15.7" figment.workspace = true httpdate = "1.0.3" +http.workspace = true +http-body.workspace = true +http-body-util.workspace = true hyper.workspace = true ipnetwork = "0.20.0" itertools = "0.13.0" diff --git a/crates/cli/src/commands/debug.rs b/crates/cli/src/commands/debug.rs index 740d0cc43..8404ef490 100644 --- a/crates/cli/src/commands/debug.rs +++ b/crates/cli/src/commands/debug.rs @@ -1,4 +1,4 @@ -// Copyright 2022 The Matrix.org Foundation C.I.C. +// Copyright 2022-2024 The Matrix.org Foundation C.I.C. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ use clap::Parser; use figment::Figment; +use http_body_util::BodyExt; use hyper::{Response, Uri}; use mas_config::{ConfigurationSection, PolicyConfig}; use mas_handlers::HttpClientFactory; @@ -79,7 +80,7 @@ impl Options { let mut client = http_client_factory.client("debug"); let request = hyper::Request::builder() .uri(url) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let response = client.ready().await?.call(request).await?; let (parts, body) = response.into_parts(); @@ -88,7 +89,7 @@ impl Options { print_headers(&parts); } - let mut body = hyper::body::aggregate(body).await?; + let mut body = body.collect().await?.to_bytes(); let mut stdout = tokio::io::stdout(); stdout.write_all_buf(&mut body).await?; } @@ -105,7 +106,7 @@ impl Options { .json_response(); let request = hyper::Request::builder() .uri(url) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let response: Response = client.ready().await?.call(request).await?; diff --git a/crates/cli/src/commands/doctor.rs b/crates/cli/src/commands/doctor.rs index 325c3f80b..e75bb4f4d 100644 --- a/crates/cli/src/commands/doctor.rs +++ b/crates/cli/src/commands/doctor.rs @@ -68,7 +68,7 @@ This means some clients will refuse to use it."# let request = hyper::Request::builder() .uri(&well_known_uri) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; let expected_well_known = serde_json::json!({ @@ -180,7 +180,7 @@ Error details: {e} let client_versions = hs_api.join("/_matrix/client/versions")?; let request = hyper::Request::builder() .uri(client_versions.as_str()) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; let can_reach_cs = match result { Ok(response) => { @@ -234,7 +234,7 @@ Error details: {e} "Bearer averyinvalidtokenireallyhopethisisnotvalid", ) .uri(whoami.as_str()) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; match result { Ok(response) => { @@ -284,7 +284,7 @@ Error details: {e} let server_version = hs_api.join("/_synapse/admin/v1/server_version")?; let request = hyper::Request::builder() .uri(server_version.as_str()) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; match result { Ok(response) => { @@ -313,7 +313,7 @@ Error details: {e} let request = hyper::Request::builder() .uri(background_updates.as_str()) .header("Authorization", format!("Bearer {admin_token}")) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; match result { Ok(response) => { @@ -361,7 +361,7 @@ Error details: {e} let compat_login = compat_login.as_str(); let request = hyper::Request::builder() .uri(compat_login) - .body(hyper::Body::empty())?; + .body(axum::body::Body::empty())?; let result = client.ready().await?.call(request).await; match result { Ok(response) => { diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 775d4da3f..ad5352b16 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -59,11 +59,18 @@ async fn try_main() -> anyhow::Result<()> { let (log_writer, _guard) = tracing_appender::non_blocking(output); let fmt_layer = tracing_subscriber::fmt::layer() .with_writer(log_writer) + .with_file(true) + .with_line_number(true) .with_ansi(with_ansi); let filter_layer = EnvFilter::try_from_default_env() .or_else(|_| EnvFilter::try_new("info")) .context("could not setup logging filter")?; + // Setup the rustls crypto provider + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .map_err(|_| anyhow::anyhow!("could not install the AWS LC crypto provider"))?; + // Parse the CLI arguments let opts = self::commands::Options::parse(); diff --git a/crates/cli/src/sentry_transport/mod.rs b/crates/cli/src/sentry_transport/mod.rs index 2fa2816dc..cc1bf06fb 100644 --- a/crates/cli/src/sentry_transport/mod.rs +++ b/crates/cli/src/sentry_transport/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 The Matrix.org Foundation C.I.C. +// Copyright 2023-2024 The Matrix.org Foundation C.I.C. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,7 +22,10 @@ use std::{sync::Arc, time::Duration}; -use hyper::{client::connect::Connect, header::RETRY_AFTER, Client, StatusCode}; +use bytes::Bytes; +use http_body_util::{BodyExt, Full}; +use hyper::{header::RETRY_AFTER, StatusCode}; +use mas_http::UntracedClient; use sentry::{sentry_debug, ClientOptions, Transport, TransportFactory}; use self::tokio_thread::TransportThread; @@ -34,30 +37,24 @@ pub struct HyperTransport { thread: TransportThread, } -pub struct HyperTransportFactory { - client: Client, +pub struct HyperTransportFactory { + client: UntracedClient>, } -impl HyperTransportFactory { - pub fn new(client: Client) -> Self { +impl HyperTransportFactory { + pub fn new(client: UntracedClient>) -> Self { Self { client } } } -impl TransportFactory for HyperTransportFactory -where - C: Connect + Clone + Send + Sync + 'static, -{ +impl TransportFactory for HyperTransportFactory { fn create_transport(&self, options: &ClientOptions) -> Arc { Arc::new(HyperTransport::new(options, self.client.clone())) } } impl HyperTransport { - pub fn new(options: &ClientOptions, client: Client) -> Self - where - C: Connect + Clone + Send + Sync + 'static, - { + pub fn new(options: &ClientOptions, client: UntracedClient>) -> Self { let dsn = options.dsn.as_ref().unwrap(); let user_agent = options.user_agent.clone(); let auth = dsn.to_auth(Some(&user_agent)).to_string(); @@ -69,7 +66,7 @@ impl HyperTransport { let request = hyper::Request::post(&url) .header("X-Sentry-Auth", &auth) - .body(hyper::Body::from(body)) + .body(Full::new(Bytes::from(body))) .unwrap(); let fut = client.request(request); @@ -93,12 +90,13 @@ impl HyperTransport { rl.update_from_429(); } - match hyper::body::to_bytes(response.into_body()).await { + match response.into_body().collect().await { Err(err) => { sentry_debug!("Failed to read sentry response: {}", err); } - Ok(bytes) => { - let text = String::from_utf8_lossy(&bytes); + Ok(body) => { + let body = body.to_bytes(); + let text = String::from_utf8_lossy(&body); sentry_debug!("Get response: `{}`", text); } } diff --git a/crates/cli/src/server.rs b/crates/cli/src/server.rs index 70ad823ca..2d6666f20 100644 --- a/crates/cli/src/server.rs +++ b/crates/cli/src/server.rs @@ -1,4 +1,4 @@ -// Copyright 2022 The Matrix.org Foundation C.I.C. +// Copyright 2022-2024 The Matrix.org Foundation C.I.C. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ use std::{ use anyhow::Context; use axum::{ - body::HttpBody, error_handling::HandleErrorLayer, extract::{FromRef, MatchedPath}, Extension, Router, @@ -39,7 +38,6 @@ use mas_tower::{ KV, }; use opentelemetry::{Key, KeyValue}; -use opentelemetry_http::HeaderExtractor; use opentelemetry_semantic_conventions::trace::{ HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, HTTP_ROUTE, NETWORK_PROTOCOL_NAME, NETWORK_PROTOCOL_VERSION, URL_PATH, URL_QUERY, URL_SCHEME, USER_AGENT_ORIGINAL, @@ -55,6 +53,22 @@ use crate::app_state::AppState; const MAS_LISTENER_NAME: Key = Key::from_static_str("mas.listener.name"); +/// Same as the extractor from opentelemetry-http, but using http@1 +struct HeaderExtractor<'a>(pub &'a http::HeaderMap); + +impl<'a> opentelemetry::propagation::Extractor for HeaderExtractor<'a> { + fn get(&self, key: &str) -> Option<&str> { + self.0.get(key).and_then(|value| value.to_str().ok()) + } + + fn keys(&self) -> Vec<&str> { + self.0 + .keys() + .map(http::HeaderName::as_str) + .collect::>() + } +} + #[inline] fn otel_http_method(request: &Request) -> &'static str { match request.method() { @@ -179,36 +193,31 @@ fn on_http_response_labels(res: &Response) -> Vec { )] } -pub fn build_router( +pub fn build_router( state: AppState, resources: &[HttpResource], prefix: Option<&str>, name: Option<&str>, -) -> Router<(), B> -where - B: HttpBody + Send + 'static, - ::Data: Into + Send, - ::Error: std::error::Error + Send + Sync, -{ +) -> Router<()> { let templates = Templates::from_ref(&state); let mut router = Router::new(); for resource in resources { router = match resource { mas_config::HttpResource::Health => { - router.merge(mas_handlers::healthcheck_router::()) + router.merge(mas_handlers::healthcheck_router::()) } mas_config::HttpResource::Prometheus => { router.route_service("/metrics", crate::telemetry::prometheus_service()) } mas_config::HttpResource::Discovery => { - router.merge(mas_handlers::discovery_router::()) + router.merge(mas_handlers::discovery_router::()) } mas_config::HttpResource::Human => { - router.merge(mas_handlers::human_router::(templates.clone())) + router.merge(mas_handlers::human_router::(templates.clone())) } mas_config::HttpResource::GraphQL { playground } => { - router.merge(mas_handlers::graphql_router::(*playground)) + router.merge(mas_handlers::graphql_router::(*playground)) } mas_config::HttpResource::Assets { path } => { let static_service = ServeDir::new(path) @@ -230,11 +239,9 @@ where (error_layer, cache_layer).layer(static_service), ) } - mas_config::HttpResource::OAuth => { - router.merge(mas_handlers::api_router::()) - } + mas_config::HttpResource::OAuth => router.merge(mas_handlers::api_router::()), mas_config::HttpResource::Compat => { - router.merge(mas_handlers::compat_router::()) + router.merge(mas_handlers::compat_router::()) } // TODO: do a better handler here mas_config::HttpResource::ConnectionInfo => router.route( diff --git a/crates/cli/src/telemetry.rs b/crates/cli/src/telemetry.rs index 5f54dc54c..c83e7a0c4 100644 --- a/crates/cli/src/telemetry.rs +++ b/crates/cli/src/telemetry.rs @@ -15,6 +15,8 @@ use std::time::Duration; use anyhow::Context as _; +use bytes::Bytes; +use http_body_util::Full; use hyper::{header::CONTENT_TYPE, Response}; use mas_config::{ MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig, @@ -48,7 +50,16 @@ static METER_PROVIDER: OnceCell = OnceCell::const_new(); static PROMETHEUS_REGISTRY: OnceCell = OnceCell::const_new(); pub fn setup(config: &TelemetryConfig) -> anyhow::Result> { - global::set_error_handler(|e| tracing::error!("{}", e))?; + global::set_error_handler(|e| { + // Don't log the propagation errors, else we'll log an error on each request if + // the propagation errors aren't there + if matches!(e, opentelemetry::global::Error::Propagation(_)) { + return; + } + + tracing::error!(error = &e as &dyn std::error::Error); + })?; + let propagator = propagator(&config.tracing.propagators); // The CORS filter needs to know what headers it should whitelist for @@ -162,14 +173,15 @@ fn stdout_metric_reader() -> PeriodicReader { PeriodicReader::builder(exporter, opentelemetry_sdk::runtime::Tokio).build() } -type PromServiceFuture = std::future::Ready, std::convert::Infallible>>; +type PromServiceFuture = + std::future::Ready>, std::convert::Infallible>>; #[allow(clippy::needless_pass_by_value)] fn prometheus_service_fn(_req: T) -> PromServiceFuture { use prometheus::{Encoder, TextEncoder}; let response = if let Some(registry) = PROMETHEUS_REGISTRY.get() { - let mut buffer = String::new(); + let mut buffer = Vec::new(); let encoder = TextEncoder::new(); let metric_families = registry.gather(); @@ -179,13 +191,15 @@ fn prometheus_service_fn(_req: T) -> PromServiceFuture { Response::builder() .status(200) .header(CONTENT_TYPE, encoder.format_type()) - .body(buffer) + .body(Full::new(Bytes::from(buffer))) .unwrap() } else { Response::builder() .status(500) .header(CONTENT_TYPE, "text/plain") - .body(Body::from("Prometheus exporter was not enabled in config")) + .body(Full::new(Bytes::from_static( + b"Prometheus exporter was not enabled in config", + ))) .unwrap() }; diff --git a/crates/http/Cargo.toml b/crates/http/Cargo.toml index c47b08d6b..bf827c3cb 100644 --- a/crates/http/Cargo.toml +++ b/crates/http/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] async-trait.workspace = true -bytes = "1.6.0" +bytes.workspace = true futures-util = "0.3.30" headers.workspace = true http.workspace = true diff --git a/crates/listener/Cargo.toml b/crates/listener/Cargo.toml index d15ea9a6c..cd58169fd 100644 --- a/crates/listener/Cargo.toml +++ b/crates/listener/Cargo.toml @@ -12,7 +12,7 @@ publish = false workspace = true [dependencies] -bytes = "1.6.0" +bytes.workspace = true event-listener = "5.3.1" futures-util = "0.3.30" http-body.workspace = true diff --git a/crates/oidc-client/Cargo.toml b/crates/oidc-client/Cargo.toml index 6332b04dc..f869b7909 100644 --- a/crates/oidc-client/Cargo.toml +++ b/crates/oidc-client/Cargo.toml @@ -17,7 +17,7 @@ keystore = ["dep:mas-keystore"] [dependencies] base64ct = { version = "1.6.0", features = ["std"] } -bytes = "1.6.0" +bytes.workspace = true chrono.workspace = true form_urlencoded = "1.2.1" futures-util = "0.3.30" From 93a014cd40e6b3f0689f62959eb8cfc6d57d3612 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 15:24:18 +0200 Subject: [PATCH 13/16] Update some dependencies and the cargo-deny allowlist --- Cargo.lock | 73 ++++++++++++++++++++++++++------------ Cargo.toml | 6 ++-- crates/handlers/Cargo.toml | 2 +- crates/i18n/Cargo.toml | 6 ++-- deny.toml | 10 ++++-- 5 files changed, 66 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a9203c1f..c5a0eb4e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,9 +571,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.6.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33e4a55b03f8780ba55041bc7be91a2a8ec8c03517b0379d2d6c96d2c30d95" +checksum = "a8a47f2fb521b70c11ce7369a6c5fa4bd6af7e5d62ec06303875bafe7c6ba245" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -583,11 +583,12 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.13.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ede3d6e360a48436fee127cb81710834407b1ec0c48a001cc29dec9005f73e" +checksum = "2927c7af777b460b7ccd95f8b67acd7b4c04ec8896bf0c8e80ba30523cffc057" dependencies = [ "bindgen", + "cc", "cmake", "dunce", "fs_extra", @@ -886,6 +887,11 @@ name = "cc" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] [[package]] name = "cesu8" @@ -999,9 +1005,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -2845,6 +2851,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -3776,9 +3791,9 @@ dependencies = [ [[package]] name = "minijinja" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e136ef580d7955019ab0a407b68d77c292a9976907e217900f3f76bc8f6dc1a4" +checksum = "933ee10775d58fca8238a84fe165dfe4bde8b07d7574f24d76ffea91170f3ac6" dependencies = [ "memo-map", "self_cell", @@ -4320,9 +4335,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -4331,9 +4346,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -4341,9 +4356,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -4354,9 +4369,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -4567,9 +4582,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", "syn 2.0.68", @@ -4661,9 +4676,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "psl" -version = "2.1.49" +version = "2.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11928d9b009645f617a3ff75bd992ff150dd239b1ad8e2949d36c0dc998438a" +checksum = "20f2890e9f6f068d927643e8d547931b537f21fd298e197c4837f1265b11e560" dependencies = [ "psl-types", ] @@ -5480,9 +5495,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.119" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap 2.2.6", "itoa", @@ -7365,6 +7380,20 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] [[package]] name = "zerotrie" diff --git a/Cargo.toml b/Cargo.toml index dae4e6804..f35024a29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,7 +157,7 @@ features = [ # Templates [workspace.dependencies.minijinja] -version = "2.0.2" +version = "2.0.3" # Random values [workspace.dependencies.rand] @@ -169,7 +169,7 @@ version = "0.23.10" # Use platform-specific verifier for TLS [workspace.dependencies.rustls-platform-verifier] -version = "0.3.1" +version = "0.3.2" # JSON Schema generation [workspace.dependencies.schemars] @@ -198,7 +198,7 @@ features = ["derive"] # Most of the time, if we need serde, we need derive # JSON serialization and deserialization [workspace.dependencies.serde_json] -version = "1.0.119" +version = "1.0.120" features = ["preserve_order"] # SQL database support diff --git a/crates/handlers/Cargo.toml b/crates/handlers/Cargo.toml index e3977dc81..4d4fd04fb 100644 --- a/crates/handlers/Cargo.toml +++ b/crates/handlers/Cargo.toml @@ -65,7 +65,7 @@ zeroize = "1.8.1" base64ct = "1.6.0" camino.workspace = true chrono.workspace = true -psl = "2.1.49" +psl = "2.1.50" time = "0.3.36" url.workspace = true mime = "0.3.17" diff --git a/crates/i18n/Cargo.toml b/crates/i18n/Cargo.toml index fec41f375..af04dada6 100644 --- a/crates/i18n/Cargo.toml +++ b/crates/i18n/Cargo.toml @@ -16,15 +16,15 @@ camino.workspace = true icu_calendar = { version = "1.4.0", features = ["compiled_data", "std"] } icu_datetime = { version = "1.4.0", features = ["compiled_data", "std"] } icu_list = { version = "1.4.0", features = ["compiled_data", "std"] } -icu_locid = { version = "1.4.0", features = ["std",] } +icu_locid = { version = "1.4.0", features = ["std"] } icu_locid_transform = { version = "1.4.0", features = ["compiled_data", "std"] } icu_plurals = { version = "1.4.0", features = ["compiled_data", "std"] } icu_provider = { version = "1.4.0", features = ["std", "sync"] } icu_provider_adapters = { version = "1.4.0", features = ["std"] } icu_relativetime = { version = "0.1.4", features = ["compiled_data", "std"] } pad = "0.1.6" -pest = "2.7.10" -pest_derive = "2.7.10" +pest = "2.7.11" +pest_derive = "2.7.11" serde.workspace = true serde_json.workspace = true thiserror.workspace = true diff --git a/deny.toml b/deny.toml index fd28a6a54..8c7788aa5 100644 --- a/deny.toml +++ b/deny.toml @@ -52,7 +52,6 @@ deny = [ multiple-versions = "deny" skip = [ - { name = "base64", version = "0.13.1" }, # async-graphql depends on this old version { name = "base64", version = "0.21.7" }, # many dependencies depends on this old version { name = "syn", version = "1.0.109" }, # sea-query, sqlx, schemars depend on the old version { name = "event-listener", version = "2.5.3" }, # async-channel (wiremock) and sqlx-core depend on the old version @@ -60,7 +59,6 @@ skip = [ { name = "regex-automata", version = "0.1.10" }, # ^ { name = "regex-automata", version = "0.2.0" }, # icu_list depends on this old version { name = "indexmap", version = "1.9.3" }, # schemars depends on this old version - { name = "bitflags", version = "1.3.2" }, # axum depends on an old version { name = "hashbrown" }, # Too many versions :( # sqlx uses old versions of those: { name = "rustls", version = "0.21.10" }, @@ -69,6 +67,7 @@ skip = [ { name = "webpki-roots", version = "0.25.3" }, # axum-macros, sqlx-macros and sea-query-attr use an old version { name = "heck", version = "0.4.1" }, + # opentelemetry-http needs this { name = "http", version = "0.2.12" }, # sea-query-attr uses an old version of darling { name = "darling", version = "0.14.4" }, @@ -80,6 +79,13 @@ skip = [ { name = "itertools", version = "0.12.1" }, # wasmtime -> cranelift is depending on this old version { name = "gimli", version = "0.28.1" }, + # opentelemetry-otlp -> -proto -> tonic is depending on this old version + { name = "http-body", version = "0.4.6" }, + # apalis-core depends on this old version + { name = "strum", version = "0.25.0" }, + { name = "strum_macros", version = "0.25.0" }, + # For some reason, axum-core depends on this old version, even though axum is on the new one + { name = "sync_wrapper", version = "0.1.2" }, ] skip-tree = [] From 184963c1d0067c3971a9c8a2377e93bd79ff8a89 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 15:35:58 +0200 Subject: [PATCH 14/16] Update the schema --- frontend/.eslintrc.cjs | 3 +++ frontend/schema.graphql | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index 45882724c..c220a7f3c 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -107,6 +107,9 @@ module.exports = { }, ], + // async-graphql generates a few unused directives, let's not warn about them + "@graphql-eslint/no-unreachable-types": "off", + // We need to disable this rule because of the 'username' field in the 'User' node "@graphql-eslint/no-typename-prefix": "off", diff --git a/frontend/schema.graphql b/frontend/schema.graphql index 3688b671b..dbbc4b59e 100644 --- a/frontend/schema.graphql +++ b/frontend/schema.graphql @@ -1857,6 +1857,12 @@ Represents the current viewer's session """ union ViewerSession = BrowserSession | Oauth2Session | Anonymous +directive @deprecated( + reason: String = "No longer supported" +) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE +directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT +directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT +directive @specifiedBy(url: String!) on SCALAR schema { query: Query mutation: Mutation From fad9e10498c50b2dade4724ffeb4b8bd18a573e4 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 2 Jul 2024 16:12:10 +0200 Subject: [PATCH 15/16] Initialize the crypto backend in the mas-oidc-client tests --- Cargo.lock | 1 + crates/oidc-client/Cargo.toml | 1 + crates/oidc-client/tests/it/main.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index c5a0eb4e1..03058c2a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3542,6 +3542,7 @@ dependencies = [ "oauth2-types", "rand", "rand_chacha", + "rustls 0.23.10", "serde", "serde_json", "serde_urlencoded", diff --git a/crates/oidc-client/Cargo.toml b/crates/oidc-client/Cargo.toml index f869b7909..70452b4d3 100644 --- a/crates/oidc-client/Cargo.toml +++ b/crates/oidc-client/Cargo.toml @@ -49,5 +49,6 @@ rand_chacha = "0.3.1" tokio.workspace = true wiremock = "0.6.0" http-body-util.workspace = true +rustls.workspace = true mas-http = { workspace = true, features = ["client"] } diff --git a/crates/oidc-client/tests/it/main.rs b/crates/oidc-client/tests/it/main.rs index e818ac5bb..de45ba986 100644 --- a/crates/oidc-client/tests/it/main.rs +++ b/crates/oidc-client/tests/it/main.rs @@ -64,6 +64,8 @@ fn now() -> DateTime { } async fn init_test() -> (HttpService, MockServer, Url) { + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let http_service = ( MapErrLayer::new(BoxError::from), MapRequestLayer::new(|req: http::Request<_>| req.map(Full::new)), From 17e639e84279aa7d169613153b76401bc9c42278 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 5 Jul 2024 09:56:37 +0200 Subject: [PATCH 16/16] Fix a reference in a doc comment --- crates/tower/src/trace_context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/tower/src/trace_context.rs b/crates/tower/src/trace_context.rs index 83b1cee03..3df9c1e43 100644 --- a/crates/tower/src/trace_context.rs +++ b/crates/tower/src/trace_context.rs @@ -22,8 +22,8 @@ use tracing_opentelemetry::OpenTelemetrySpanExt; pub struct HeaderInjector<'a>(pub &'a mut http::HeaderMap); impl<'a> Injector for HeaderInjector<'a> { - /// Set a key and value in the [`HeaderMap`]. Does nothing if the key or - /// value are not valid inputs. + /// Set a key and value in the [`http::HeaderMap`]. Does nothing if the key + /// or value are not valid inputs. fn set(&mut self, key: &str, value: String) { if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) { if let Ok(val) = http::header::HeaderValue::from_str(&value) {