From c77d0686aa495e5a291e17230a5b62dec88d27f1 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 15:06:06 +0900 Subject: [PATCH 01/24] HTTP proxy --- src/client.rs | 20 ++++++++++++++------ src/db.rs | 1 + src/main.rs | 7 +++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/client.rs b/src/client.rs index 84819353..958ec9e7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -171,6 +171,7 @@ pub struct Client { pub redirect_limit: usize, pub disable_keepalive: bool, pub insecure: bool, + pub proxy_url: Option, #[cfg(unix)] pub unix_socket: Option, #[cfg(feature = "vsock")] @@ -369,7 +370,12 @@ impl Client { Err(_) => Err(ClientError::Timeout), }; } - let addr = self.dns.lookup(url, rng).await?; + // HTTP + let addr = if let Some(proxy_url) = &self.proxy_url { + self.dns.lookup(proxy_url, rng).await? + } else { + self.dns.lookup(url, rng).await? + }; let dns_lookup = Instant::now(); let stream = tokio::time::timeout(timeout_duration, tokio::net::TcpStream::connect(addr)).await; @@ -451,11 +457,13 @@ impl Client { fn request(&self, url: &Url) -> Result>, ClientError> { let mut builder = http::Request::builder() - .uri(if self.is_http2() { - &url[..] - } else { - &url[url::Position::BeforePath..] - }) + .uri( + if self.is_http2() || (url.scheme() == "http" && self.proxy_url.is_some()) { + &url[..] + } else { + &url[url::Position::BeforePath..] + }, + ) .method(self.method.clone()) .version(self.http_version); diff --git a/src/db.rs b/src/db.rs index ed212a92..63145672 100644 --- a/src/db.rs +++ b/src/db.rs @@ -86,6 +86,7 @@ mod test_db { redirect_limit: 0, disable_keepalive: false, insecure: false, + proxy_url: None, #[cfg(unix)] unix_socket: None, #[cfg(feature = "vsock")] diff --git a/src/main.rs b/src/main.rs index 8ae00ab7..ff7dc235 100644 --- a/src/main.rs +++ b/src/main.rs @@ -134,10 +134,8 @@ Note: If qps is specified, burst will be ignored", content_type: Option, #[arg(help = "Basic authentication, username:password", short = 'a')] basic_auth: Option, - /* - #[arg(help = "HTTP proxy", short = "x")] - proxy: Option, - */ + #[arg(help = "HTTP proxy", short = 'x')] + proxy: Option, #[arg( help = "HTTP version. Available values 0.9, 1.0, 1.1.", long = "http-version" @@ -459,6 +457,7 @@ async fn main() -> anyhow::Result<()> { redirect_limit: opts.redirect, disable_keepalive: opts.disable_keepalive, insecure: opts.insecure, + proxy_url: opts.proxy, #[cfg(unix)] unix_socket: opts.unix_socket, #[cfg(feature = "vsock")] From f2513a8002a4ebb8c080bfde1ddab70db73a5cb8 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 15:51:13 +0900 Subject: [PATCH 02/24] wip --- src/client.rs | 97 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/src/client.rs b/src/client.rs index 958ec9e7..7d44ebab 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,5 +1,5 @@ use http_body_util::{BodyExt, Full}; -use hyper::http; +use hyper::{http, Method, Version}; use hyper_util::rt::{TokioExecutor, TokioIo}; use rand::prelude::*; use std::{ @@ -11,7 +11,10 @@ use std::{ time::Instant, }; use thiserror::Error; -use tokio::net::TcpStream; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + net::TcpStream, +}; use url::{ParseError, Url}; use crate::{ @@ -228,32 +231,48 @@ enum Stream { } impl Stream { - async fn handshake_http1(self) -> Result { + async fn handshake_http1(self, with_upgrade: bool) -> Result { match self { Stream::Tcp(stream) => { let (send_request, conn) = hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; - tokio::spawn(conn); + if with_upgrade { + tokio::spawn(conn.with_upgrades()); + } else { + tokio::spawn(conn); + } Ok(send_request) } Stream::Tls(stream) => { let (send_request, conn) = hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; - tokio::spawn(conn); + if with_upgrade { + tokio::spawn(conn.with_upgrades()); + } else { + tokio::spawn(conn); + } Ok(send_request) } #[cfg(unix)] Stream::Unix(stream) => { let (send_request, conn) = hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; - tokio::spawn(conn); + if with_upgrade { + tokio::spawn(conn.with_upgrades()); + } else { + tokio::spawn(conn); + } Ok(send_request) } #[cfg(feature = "vsock")] Stream::Vsock(stream) => { let (send_request, conn) = hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; - tokio::spawn(conn); + if with_upgrade { + tokio::spawn(conn.with_upgrades()); + } else { + tokio::spawn(conn); + } Ok(send_request) } } @@ -371,11 +390,7 @@ impl Client { }; } // HTTP - let addr = if let Some(proxy_url) = &self.proxy_url { - self.dns.lookup(proxy_url, rng).await? - } else { - self.dns.lookup(url, rng).await? - }; + let addr = self.dns.lookup(url, rng).await?; let dns_lookup = Instant::now(); let stream = tokio::time::timeout(timeout_duration, tokio::net::TcpStream::connect(addr)).await; @@ -446,13 +461,67 @@ impl Client { Ok(Stream::Tls(stream)) } + #[cfg(feature = "rustls")] + async fn connect_tls( + &self, + stream: S, + url: &Url, + ) -> Result, ClientError> + where + S: AsyncRead + AsyncWrite + Unpin, + { + let mut config = rustls::ClientConfig::builder() + .with_root_certificates(self.root_cert_store.clone()) + .with_no_client_auth(); + if self.insecure { + config + .dangerous() + .set_certificate_verifier(Arc::new(AcceptAnyServerCert)); + } + if self.is_http2() { + config.alpn_protocols = vec![b"h2".to_vec()]; + } + let connector = tokio_rustls::TlsConnector::from(Arc::new(config)); + let domain = rustls_pki_types::ServerName::try_from( + url.host_str().ok_or(ClientError::HostNotFound)?, + )?; + let stream = connector.connect(domain.to_owned(), stream).await?; + + Ok(stream) + } + async fn client_http1( &self, url: &Url, rng: &mut R, ) -> Result<(Instant, SendRequestHttp1), ClientError> { - let (dns_lookup, stream) = self.client(url, rng).await?; - Ok((dns_lookup, stream.handshake_http1().await?)) + if let Some(proxy_url) = &self.proxy_url { + let (dns_lookup, stream) = self.client(proxy_url, rng).await?; + if url.scheme() == "https" { + // Do CONNECT request to proxy + let mut send_request = stream.handshake_http1(true).await?; + let req = http::Request::builder() + .method(Method::CONNECT) + .uri(format!( + "{}:{}", + url.host_str().unwrap(), + url.port_or_known_default().unwrap() + )) + .body(http_body_util::Full::default())?; + let res = send_request.send_request(req).await?; + let stream = hyper::upgrade::on(res).await?; + let stream = self.connect_tls(TokioIo::new(stream), url).await?; + let (send_request, conn) = + hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; + tokio::spawn(conn); + Ok((dns_lookup, send_request)) + } else { + Ok((dns_lookup, stream.handshake_http1(false).await?)) + } + } else { + let (dns_lookup, stream) = self.client(url, rng).await?; + Ok((dns_lookup, stream.handshake_http1(false).await?)) + } } fn request(&self, url: &Url) -> Result>, ClientError> { From d38deb7ff40dd070b88a7b34b0a290cfaa3726ad Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 15:55:54 +0900 Subject: [PATCH 03/24] wip --- src/client.rs | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/src/client.rs b/src/client.rs index 7d44ebab..2b4e1253 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,5 +1,5 @@ use http_body_util::{BodyExt, Full}; -use hyper::{http, Method, Version}; +use hyper::{http, Method}; use hyper_util::rt::{TokioExecutor, TokioIo}; use rand::prelude::*; use std::{ @@ -404,7 +404,6 @@ impl Client { } } - #[cfg(all(feature = "native-tls", not(feature = "rustls")))] async fn tls_client( &self, addr: (std::net::IpAddr, u16), @@ -413,6 +412,20 @@ impl Client { let stream = tokio::net::TcpStream::connect(addr).await?; stream.set_nodelay(true)?; + let stream = self.connect_tls(stream, url).await?; + + Ok(Stream::Tls(stream)) + } + + #[cfg(all(feature = "native-tls", not(feature = "rustls")))] + async fn connect_tls( + &self, + stream: S, + url: &Url, + ) -> Result, ClientError> + where + S: AsyncRead + AsyncWrite + Unpin, + { let mut connector_builder = native_tls::TlsConnector::builder(); if self.insecure { connector_builder @@ -429,36 +442,7 @@ impl Client { .connect(url.host_str().ok_or(ClientError::HostNotFound)?, stream) .await?; - Ok(Stream::Tls(stream)) - } - - #[cfg(feature = "rustls")] - async fn tls_client( - &self, - addr: (std::net::IpAddr, u16), - url: &Url, - ) -> Result { - let stream = tokio::net::TcpStream::connect(addr).await?; - stream.set_nodelay(true)?; - - let mut config = rustls::ClientConfig::builder() - .with_root_certificates(self.root_cert_store.clone()) - .with_no_client_auth(); - if self.insecure { - config - .dangerous() - .set_certificate_verifier(Arc::new(AcceptAnyServerCert)); - } - if self.is_http2() { - config.alpn_protocols = vec![b"h2".to_vec()]; - } - let connector = tokio_rustls::TlsConnector::from(Arc::new(config)); - let domain = rustls_pki_types::ServerName::try_from( - url.host_str().ok_or(ClientError::HostNotFound)?, - )?; - let stream = connector.connect(domain.to_owned(), stream).await?; - - Ok(Stream::Tls(stream)) + Ok(stream) } #[cfg(feature = "rustls")] From 107a297a4b610991abb3d8db0c38d03cdcc7286a Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 16:23:38 +0900 Subject: [PATCH 04/24] wip --- src/client.rs | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/client.rs b/src/client.rs index 2b4e1253..32e7c719 100644 --- a/src/client.rs +++ b/src/client.rs @@ -500,6 +500,7 @@ impl Client { tokio::spawn(conn); Ok((dns_lookup, send_request)) } else { + // Send full URL in request() for HTTP proxy Ok((dns_lookup, stream.handshake_http1(false).await?)) } } else { @@ -632,10 +633,42 @@ impl Client { url: &Url, rng: &mut R, ) -> Result<(ConnectionTime, SendRequestHttp2), ClientError> { - let (dns_lookup, stream) = self.client(url, rng).await?; - let send_request = stream.handshake_http2().await?; - let dialup = std::time::Instant::now(); - Ok((ConnectionTime { dns_lookup, dialup }, send_request)) + if let Some(proxy_url) = &self.proxy_url { + if url.scheme() == "https" { + let (dns_lookup, stream) = self.client(proxy_url, rng).await?; + let mut send_request = stream.handshake_http2().await?; + let req = http::Request::builder() + .method(Method::CONNECT) + .uri(format!( + "{}:{}", + url.host_str().unwrap(), + url.port_or_known_default().unwrap() + )) + .body(http_body_util::Full::default())?; + let res = send_request.send_request(req).await?; + let stream = hyper::upgrade::on(res).await?; + let dialup = std::time::Instant::now(); + let stream = self.connect_tls(TokioIo::new(stream), url).await?; + let (send_request, conn) = hyper::client::conn::http2::handshake( + TokioExecutor::new(), + TokioIo::new(stream), + ) + .await?; + tokio::spawn(conn); + + Ok((ConnectionTime { dns_lookup, dialup }, send_request)) + } else { + let (dns_lookup, stream) = self.client(proxy_url, rng).await?; + let send_request = stream.handshake_http2().await?; + let dialup = std::time::Instant::now(); + Ok((ConnectionTime { dns_lookup, dialup }, send_request)) + } + } else { + let (dns_lookup, stream) = self.client(url, rng).await?; + let send_request = stream.handshake_http2().await?; + let dialup = std::time::Instant::now(); + Ok((ConnectionTime { dns_lookup, dialup }, send_request)) + } } async fn work_http2( From d58ec160f76ea544d2ec9c1d1f4b19300c894154 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 16:41:22 +0900 Subject: [PATCH 05/24] wip --- src/client.rs | 31 ++++++++++++++++++++++--------- src/db.rs | 1 + src/main.rs | 7 +++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/client.rs b/src/client.rs index 32e7c719..83ff6241 100644 --- a/src/client.rs +++ b/src/client.rs @@ -165,6 +165,7 @@ pub enum ClientError { pub struct Client { pub http_version: http::Version, + pub proxy_http_version: http::Version, pub url_generator: UrlGenerator, pub method: http::Method, pub headers: http::header::HeaderMap, @@ -483,7 +484,6 @@ impl Client { let (dns_lookup, stream) = self.client(proxy_url, rng).await?; if url.scheme() == "https" { // Do CONNECT request to proxy - let mut send_request = stream.handshake_http1(true).await?; let req = http::Request::builder() .method(Method::CONNECT) .uri(format!( @@ -492,7 +492,13 @@ impl Client { url.port_or_known_default().unwrap() )) .body(http_body_util::Full::default())?; - let res = send_request.send_request(req).await?; + let res = if self.proxy_http_version == http::Version::HTTP_2 { + let mut send_request = stream.handshake_http2().await?; + send_request.send_request(req).await? + } else { + let mut send_request = stream.handshake_http1(true).await?; + send_request.send_request(req).await? + }; let stream = hyper::upgrade::on(res).await?; let stream = self.connect_tls(TokioIo::new(stream), url).await?; let (send_request, conn) = @@ -636,7 +642,6 @@ impl Client { if let Some(proxy_url) = &self.proxy_url { if url.scheme() == "https" { let (dns_lookup, stream) = self.client(proxy_url, rng).await?; - let mut send_request = stream.handshake_http2().await?; let req = http::Request::builder() .method(Method::CONNECT) .uri(format!( @@ -645,15 +650,23 @@ impl Client { url.port_or_known_default().unwrap() )) .body(http_body_util::Full::default())?; - let res = send_request.send_request(req).await?; + let res = if self.proxy_http_version == http::Version::HTTP_2 { + let mut send_request = stream.handshake_http2().await?; + send_request.send_request(req).await? + } else { + let mut send_request = stream.handshake_http1(true).await?; + send_request.send_request(req).await? + }; let stream = hyper::upgrade::on(res).await?; let dialup = std::time::Instant::now(); let stream = self.connect_tls(TokioIo::new(stream), url).await?; - let (send_request, conn) = hyper::client::conn::http2::handshake( - TokioExecutor::new(), - TokioIo::new(stream), - ) - .await?; + let (send_request, conn) = + hyper::client::conn::http2::Builder::new(TokioExecutor::new()) + // from nghttp2's default + .initial_stream_window_size((1 << 30) - 1) + .initial_connection_window_size((1 << 30) - 1) + .handshake(TokioIo::new(stream)) + .await?; tokio::spawn(conn); Ok((ConnectionTime { dns_lookup, dialup }, send_request)) diff --git a/src/db.rs b/src/db.rs index 63145672..7b82ff01 100644 --- a/src/db.rs +++ b/src/db.rs @@ -74,6 +74,7 @@ mod test_db { let test_vec = vec![test_val.clone(), test_val.clone()]; let client = Client { http_version: Version::HTTP_11, + proxy_http_version: Version::HTTP_11, url_generator: UrlGenerator::new_static("http://example.com".parse().unwrap()), method: Method::GET, headers: HeaderMap::new(), diff --git a/src/main.rs b/src/main.rs index ff7dc235..a46fed4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -136,6 +136,8 @@ Note: If qps is specified, burst will be ignored", basic_auth: Option, #[arg(help = "HTTP proxy", short = 'x')] proxy: Option, + #[arg(help = "Use HTTP/2 to connect to proxy", long = "proxy-http2")] + proxy_http2: bool, #[arg( help = "HTTP version. Available values 0.9, 1.0, 1.1.", long = "http-version" @@ -445,6 +447,11 @@ async fn main() -> anyhow::Result<()> { let client = Arc::new(client::Client { http_version, + proxy_http_version: if opts.proxy_http2 { + http::Version::HTTP_2 + } else { + http::Version::HTTP_11 + }, url_generator, method: opts.method, headers, From 96b56d9247f13fbbac4530a98ec98eece54987a9 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 16:44:26 +0900 Subject: [PATCH 06/24] wip --- src/main.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index a46fed4a..fb134158 100644 --- a/src/main.rs +++ b/src/main.rs @@ -136,10 +136,18 @@ Note: If qps is specified, burst will be ignored", basic_auth: Option, #[arg(help = "HTTP proxy", short = 'x')] proxy: Option, - #[arg(help = "Use HTTP/2 to connect to proxy", long = "proxy-http2")] + #[arg( + help = "HTTP version to connect to proxy. Available values 0.9, 1.0, 1.1, 2.", + long = "proxy-http-version" + )] + proxy_http_version: Option, + #[arg( + help = "Use HTTP/2 to connect to proxy. Shorthand for --proxy-http-version=2", + long = "proxy-http2" + )] proxy_http2: bool, #[arg( - help = "HTTP version. Available values 0.9, 1.0, 1.1.", + help = "HTTP version. Available values 0.9, 1.0, 1.1, 2.", long = "http-version" )] http_version: Option, From 6f62b8beb30ad727f007871e4fa87715ed17cd38 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 16:49:08 +0900 Subject: [PATCH 07/24] wip --- src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index fb134158..8300585a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -286,20 +286,24 @@ impl FromStr for VsockAddr { async fn main() -> anyhow::Result<()> { let mut opts: Opts = Opts::parse(); - let http_version: http::Version = match (opts.http2, opts.http_version) { + let parse_http_version = |is_http2: bool, version: Option<&str>| match (is_http2, version) { (true, Some(_)) => anyhow::bail!("--http2 and --http-version are exclusive"), - (true, None) => http::Version::HTTP_2, + (true, None) => Ok(http::Version::HTTP_2), (false, Some(http_version)) => match http_version.trim() { - "0.9" => http::Version::HTTP_09, - "1.0" => http::Version::HTTP_10, - "1.1" => http::Version::HTTP_11, - "2.0" | "2" => http::Version::HTTP_2, + "0.9" => Ok(http::Version::HTTP_09), + "1.0" => Ok(http::Version::HTTP_10), + "1.1" => Ok(http::Version::HTTP_11), + "2.0" | "2" => Ok(http::Version::HTTP_2), "3.0" | "3" => anyhow::bail!("HTTP/3 is not supported yet."), _ => anyhow::bail!("Unknown HTTP version. Valid versions are 0.9, 1.0, 1.1, 2."), }, - (false, None) => http::Version::HTTP_11, + (false, None) => Ok(http::Version::HTTP_11), }; + let http_version: http::Version = parse_http_version(opts.http2, opts.http_version.as_deref())?; + let proxy_http_version: http::Version = + parse_http_version(opts.proxy_http2, opts.proxy_http_version.as_deref())?; + let url_generator = if opts.rand_regex_url { // Almost URL has dot in domain, so disable dot in regex for convenience. let dot_disabled: String = opts @@ -455,11 +459,7 @@ async fn main() -> anyhow::Result<()> { let client = Arc::new(client::Client { http_version, - proxy_http_version: if opts.proxy_http2 { - http::Version::HTTP_2 - } else { - http::Version::HTTP_11 - }, + proxy_http_version, url_generator, method: opts.method, headers, From 2448a3e86b5b3dfe4e51d7cc4c19ed109b6c507f Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 16:53:05 +0900 Subject: [PATCH 08/24] a --- src/client.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/client.rs b/src/client.rs index 83ff6241..bb04837c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -640,8 +640,8 @@ impl Client { rng: &mut R, ) -> Result<(ConnectionTime, SendRequestHttp2), ClientError> { if let Some(proxy_url) = &self.proxy_url { + let (dns_lookup, stream) = self.client(proxy_url, rng).await?; if url.scheme() == "https" { - let (dns_lookup, stream) = self.client(proxy_url, rng).await?; let req = http::Request::builder() .method(Method::CONNECT) .uri(format!( @@ -671,7 +671,6 @@ impl Client { Ok((ConnectionTime { dns_lookup, dialup }, send_request)) } else { - let (dns_lookup, stream) = self.client(proxy_url, rng).await?; let send_request = stream.handshake_http2().await?; let dialup = std::time::Instant::now(); Ok((ConnectionTime { dns_lookup, dialup }, send_request)) From d804337bb415b88ea319cac25a890290625234fc Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 17:08:23 +0900 Subject: [PATCH 09/24] fix --- src/client.rs | 56 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/client.rs b/src/client.rs index bb04837c..4d4ec0ca 100644 --- a/src/client.rs +++ b/src/client.rs @@ -317,6 +317,23 @@ impl Client { self.http_version == http::Version::HTTP_2 } + fn is_proxy_http2(&self) -> bool { + self.proxy_http_version == http::Version::HTTP_2 + } + + fn is_work_http2(&self) -> bool { + if self.proxy_url.is_some() { + let url = self.url_generator.generate(&mut thread_rng()).unwrap(); + if url.scheme() == "https" { + self.is_http2() + } else { + self.is_proxy_http2() + } + } else { + self.is_http2() + } + } + /// Perform a DNS lookup to cache it /// This is useful to avoid DNS lookup latency at the first concurrent requests pub async fn pre_lookup(&self) -> Result<(), ClientError> { @@ -348,6 +365,7 @@ impl Client { &self, url: &Url, rng: &mut R, + is_http2: bool, ) -> Result<(Instant, Stream), ClientError> { // TODO: Allow the connect timeout to be configured let timeout_duration = tokio::time::Duration::from_secs(5); @@ -357,7 +375,8 @@ impl Client { let dns_lookup = Instant::now(); // If we do not put a timeout here then the connections attempts will // linger long past the configured timeout - let stream = tokio::time::timeout(timeout_duration, self.tls_client(addr, url)).await; + let stream = + tokio::time::timeout(timeout_duration, self.tls_client(addr, url, is_http2)).await; return match stream { Ok(Ok(stream)) => Ok((dns_lookup, stream)), Ok(Err(err)) => Err(err), @@ -409,11 +428,12 @@ impl Client { &self, addr: (std::net::IpAddr, u16), url: &Url, + is_http2: bool, ) -> Result { let stream = tokio::net::TcpStream::connect(addr).await?; stream.set_nodelay(true)?; - let stream = self.connect_tls(stream, url).await?; + let stream = self.connect_tls(stream, url, is_http2).await?; Ok(Stream::Tls(stream)) } @@ -423,6 +443,7 @@ impl Client { &self, stream: S, url: &Url, + is_http2: bool, ) -> Result, ClientError> where S: AsyncRead + AsyncWrite + Unpin, @@ -434,7 +455,7 @@ impl Client { .danger_accept_invalid_hostnames(true); } - if self.is_http2() { + if is_http2 { connector_builder.request_alpns(&["h2"]); } @@ -451,6 +472,7 @@ impl Client { &self, stream: S, url: &Url, + is_http2: bool, ) -> Result, ClientError> where S: AsyncRead + AsyncWrite + Unpin, @@ -463,7 +485,7 @@ impl Client { .dangerous() .set_certificate_verifier(Arc::new(AcceptAnyServerCert)); } - if self.is_http2() { + if is_http2 { config.alpn_protocols = vec![b"h2".to_vec()]; } let connector = tokio_rustls::TlsConnector::from(Arc::new(config)); @@ -481,7 +503,7 @@ impl Client { rng: &mut R, ) -> Result<(Instant, SendRequestHttp1), ClientError> { if let Some(proxy_url) = &self.proxy_url { - let (dns_lookup, stream) = self.client(proxy_url, rng).await?; + let (dns_lookup, stream) = self.client(proxy_url, rng, self.is_proxy_http2()).await?; if url.scheme() == "https" { // Do CONNECT request to proxy let req = http::Request::builder() @@ -500,7 +522,7 @@ impl Client { send_request.send_request(req).await? }; let stream = hyper::upgrade::on(res).await?; - let stream = self.connect_tls(TokioIo::new(stream), url).await?; + let stream = self.connect_tls(TokioIo::new(stream), url, false).await?; let (send_request, conn) = hyper::client::conn::http1::handshake(TokioIo::new(stream)).await?; tokio::spawn(conn); @@ -510,7 +532,7 @@ impl Client { Ok((dns_lookup, stream.handshake_http1(false).await?)) } } else { - let (dns_lookup, stream) = self.client(url, rng).await?; + let (dns_lookup, stream) = self.client(url, rng, false).await?; Ok((dns_lookup, stream.handshake_http1(false).await?)) } } @@ -640,7 +662,7 @@ impl Client { rng: &mut R, ) -> Result<(ConnectionTime, SendRequestHttp2), ClientError> { if let Some(proxy_url) = &self.proxy_url { - let (dns_lookup, stream) = self.client(proxy_url, rng).await?; + let (dns_lookup, stream) = self.client(proxy_url, rng, self.is_proxy_http2()).await?; if url.scheme() == "https" { let req = http::Request::builder() .method(Method::CONNECT) @@ -659,7 +681,7 @@ impl Client { }; let stream = hyper::upgrade::on(res).await?; let dialup = std::time::Instant::now(); - let stream = self.connect_tls(TokioIo::new(stream), url).await?; + let stream = self.connect_tls(TokioIo::new(stream), url, true).await?; let (send_request, conn) = hyper::client::conn::http2::Builder::new(TokioExecutor::new()) // from nghttp2's default @@ -676,7 +698,7 @@ impl Client { Ok((ConnectionTime { dns_lookup, dialup }, send_request)) } } else { - let (dns_lookup, stream) = self.client(url, rng).await?; + let (dns_lookup, stream) = self.client(url, rng, true).await?; let send_request = stream.handshake_http2().await?; let dialup = std::time::Instant::now(); Ok((ConnectionTime { dns_lookup, dialup }, send_request)) @@ -931,7 +953,7 @@ pub async fn work_debug( println!("{:#?}", request); - let response = if client.is_http2() { + let response = if client.is_work_http2() { let (_, mut client_state) = client.connect_http2(&url, &mut rng).await?; client_state.send_request(request).await? } else { @@ -961,7 +983,7 @@ pub async fn work( use std::sync::atomic::{AtomicUsize, Ordering}; let counter = Arc::new(AtomicUsize::new(0)); - if client.is_http2() { + if client.is_work_http2() { let futures = (0..n_connections) .map(|_| { let report_tx = report_tx.clone(); @@ -1106,7 +1128,7 @@ pub async fn work_with_qps( Ok::<(), flume::SendError<_>>(()) }; - if client.is_http2() { + if client.is_work_http2() { let futures = (0..n_connections) .map(|_| { let report_tx = report_tx.clone(); @@ -1254,7 +1276,7 @@ pub async fn work_with_qps_latency_correction( Ok::<(), flume::SendError<_>>(()) }; - if client.is_http2() { + if client.is_work_http2() { let futures = (0..n_connections) .map(|_| { let report_tx = report_tx.clone(); @@ -1362,7 +1384,7 @@ pub async fn work_until( n_http2_parallel: usize, wait_ongoing_requests_after_deadline: bool, ) { - if client.is_http2() { + if client.is_work_http2() { // Using semaphore to control the deadline // Maybe there is a better concurrent primitive to do this let s = Arc::new(tokio::sync::Semaphore::new(0)); @@ -1543,7 +1565,7 @@ pub async fn work_until_with_qps( } }; - if client.is_http2() { + if client.is_work_http2() { let s = Arc::new(tokio::sync::Semaphore::new(0)); let futures = (0..n_connections) @@ -1725,7 +1747,7 @@ pub async fn work_until_with_qps_latency_correction( } }; - if client.is_http2() { + if client.is_work_http2() { let s = Arc::new(tokio::sync::Semaphore::new(0)); let futures = (0..n_connections) From 42e80fccd1993ca94af6f7063051e673e0eb5782 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 17:20:36 +0900 Subject: [PATCH 10/24] random inline --- src/client.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 4d4ec0ca..eddf9bd8 100644 --- a/src/client.rs +++ b/src/client.rs @@ -313,10 +313,12 @@ impl Stream { } impl Client { + #[inline] fn is_http2(&self) -> bool { self.http_version == http::Version::HTTP_2 } + #[inline] fn is_proxy_http2(&self) -> bool { self.proxy_http_version == http::Version::HTTP_2 } @@ -537,10 +539,11 @@ impl Client { } } + #[inline] fn request(&self, url: &Url) -> Result>, ClientError> { let mut builder = http::Request::builder() .uri( - if self.is_http2() || (url.scheme() == "http" && self.proxy_url.is_some()) { + if self.is_http2() || (self.proxy_url.is_some() && url.scheme() == "http") { &url[..] } else { &url[url::Position::BeforePath..] From 39f27a4efad16132f599068206e66ad2f4edb89e Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 17:23:54 +0900 Subject: [PATCH 11/24] fix --- src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index eddf9bd8..2e35e6f3 100644 --- a/src/client.rs +++ b/src/client.rs @@ -446,7 +446,7 @@ impl Client { stream: S, url: &Url, is_http2: bool, - ) -> Result, ClientError> + ) -> Result, ClientError> where S: AsyncRead + AsyncWrite + Unpin, { From 94ef087f88107f172751efe16beba6c24b07507a Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 17:28:29 +0900 Subject: [PATCH 12/24] fix http proxy dialup --- src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 2e35e6f3..50099b67 100644 --- a/src/client.rs +++ b/src/client.rs @@ -683,7 +683,6 @@ impl Client { send_request.send_request(req).await? }; let stream = hyper::upgrade::on(res).await?; - let dialup = std::time::Instant::now(); let stream = self.connect_tls(TokioIo::new(stream), url, true).await?; let (send_request, conn) = hyper::client::conn::http2::Builder::new(TokioExecutor::new()) @@ -693,6 +692,7 @@ impl Client { .handshake(TokioIo::new(stream)) .await?; tokio::spawn(conn); + let dialup = std::time::Instant::now(); Ok((ConnectionTime { dns_lookup, dialup }, send_request)) } else { From 5d468bd31da471d85d9b5358b1b7fd312f07353b Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 20:05:21 +0900 Subject: [PATCH 13/24] wip test --- Cargo.lock | 231 +++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 2 + tests/tests.rs | 68 +++++++++++++++ 3 files changed, 265 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8733c67c..fe599649 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -182,7 +182,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -340,7 +340,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -505,7 +505,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.85", + "syn 2.0.89", "which", ] @@ -577,7 +577,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", "syn_derive", ] @@ -768,7 +768,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -857,6 +857,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crossterm" version = "0.28.1" @@ -917,7 +941,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -944,7 +968,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1001,7 +1025,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1220,7 +1244,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1393,7 +1417,7 @@ dependencies = [ "ipnet", "once_cell", "rand", - "thiserror", + "thiserror 1.0.65", "tinyvec", "tokio", "tracing", @@ -1416,7 +1440,7 @@ dependencies = [ "rand", "resolv-conf", "smallvec", - "thiserror", + "thiserror 1.0.65", "tokio", "tracing", ] @@ -1486,6 +1510,28 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-mitm-proxy" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68e266156df6bc3c3f4e981a5bea8657278764f9a7557f396520ef04315257c4" +dependencies = [ + "bytes", + "futures", + "http-body-util", + "hyper", + "hyper-util", + "moka", + "native-tls", + "rcgen", + "rustls", + "thiserror 2.0.3", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tracing", +] + [[package]] name = "httparse" version = "1.9.5" @@ -1659,7 +1705,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1723,7 +1769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -2024,6 +2070,26 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +[[package]] +name = "moka" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "once_cell", + "parking_lot", + "quanta", + "rustc_version", + "smallvec", + "tagptr", + "thiserror 1.0.65", + "triomphe", + "uuid", +] + [[package]] name = "nanorand" version = "0.7.0" @@ -2192,6 +2258,7 @@ dependencies = [ "flume", "hickory-resolver", "http-body-util", + "http-mitm-proxy", "humantime", "hyper", "hyper-util", @@ -2206,6 +2273,7 @@ dependencies = [ "rand_core", "rand_regex", "ratatui", + "rcgen", "regex", "regex-syntax", "rlimit", @@ -2216,7 +2284,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.65", "tokio", "tokio-native-tls", "tokio-rustls", @@ -2253,7 +2321,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -2309,6 +2377,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2385,7 +2463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -2422,9 +2500,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2449,6 +2527,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -2531,6 +2624,28 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "raw-cpuid" +version = "11.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rcgen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.5.7" @@ -2557,7 +2672,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -2914,7 +3029,7 @@ checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3075,7 +3190,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3097,9 +3212,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -3115,7 +3230,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3141,9 +3256,15 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -3175,7 +3296,16 @@ version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.65", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] @@ -3186,7 +3316,18 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -3271,7 +3412,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3386,7 +3527,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3398,6 +3539,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "triomphe" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" + [[package]] name = "try-lock" version = "0.2.5" @@ -3512,6 +3659,9 @@ name = "uuid" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", +] [[package]] name = "uuid-simd" @@ -3598,7 +3748,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -3632,7 +3782,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3911,6 +4061,15 @@ dependencies = [ "tap", ] +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + [[package]] name = "yoke" version = "0.7.4" @@ -3931,7 +4090,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", "synstructure", ] @@ -3953,7 +4112,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -3973,7 +4132,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", "synstructure", ] @@ -4002,7 +4161,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5c6f8361..6936386a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,9 +83,11 @@ assert_cmd = "2.0.14" axum = { version = "0.7", features = ["http2"] } bytes = "1.6" float-cmp = "0.10.0" +http-mitm-proxy = "0.11.0" jsonschema = "0.26.0" lazy_static = "1.5.0" predicates = "3.1.0" +rcgen = "0.13.1" regex = "1.10.5" [target.'cfg(unix)'.dev-dependencies] diff --git a/tests/tests.rs b/tests/tests.rs index c3c50d73..2e7e93ab 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -703,6 +703,74 @@ async fn test_unix_socket() { rx.try_recv().unwrap(); } +#[tokio::test] +async fn test_proxy_http_http() { + let (tx, rx) = flume::unbounded(); + let (listener, port) = bind_port().await; + let proxy_port = PORT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + + let client = http_mitm_proxy::DefaultClient::new().unwrap(); + let proxy = http_mitm_proxy::MitmProxy::<&'static rcgen::CertifiedKey>::new(None, None); + let proxy_server = proxy + .bind( + ("127.0.0.1", proxy_port), + service_fn(move |mut req| { + let client = client.clone(); + + async move { + req.headers_mut() + .insert("x-oha-test-through-proxy", "true".parse().unwrap()); + + let (res, _) = client.send_request(req).await?; + + Ok::<_, http_mitm_proxy::default_client::Error>(res) + } + }), + ) + .await + .unwrap(); + tokio::spawn(proxy_server); + + tokio::spawn(async move { + loop { + let tx = tx.clone(); + let (tcp, _) = listener.accept().await.unwrap(); + hyper::server::conn::http1::Builder::new() + .serve_connection( + TokioIo::new(tcp), + service_fn(move |req| { + let tx = tx.clone(); + + async move { + tx.send(req).unwrap(); + Ok::<_, Infallible>(Response::new("Hello World".to_string())) + } + }), + ) + .await + .unwrap(); + } + }); + tokio::task::spawn_blocking(move || { + Command::cargo_bin("oha") + .unwrap() + .args(["--no-tui", "--debug", "-x"]) + .arg(format!("http://127.0.0.1:{proxy_port}/")) + .arg(format!("http://127.0.0.1:{port}/")) + .assert() + .success(); + }) + .await + .unwrap(); + + let req = rx.try_recv().unwrap(); + + assert_eq!( + req.headers().get("x-oha-test-through-proxy").unwrap(), + "true" + ); +} + #[test] fn test_google() { Command::cargo_bin("oha") From b0d63e32013932b93490c1032720fd6184ba20af Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 20:22:49 +0900 Subject: [PATCH 14/24] wip --- tests/tests.rs | 173 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 124 insertions(+), 49 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 2e7e93ab..e6080006 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,14 +1,21 @@ use std::{ convert::Infallible, + error::Error as StdError, + future::Future, net::{Ipv6Addr, SocketAddr}, - sync::atomic::AtomicU16, + sync::{atomic::AtomicU16, Arc}, }; use assert_cmd::Command; use axum::{extract::Path, response::Redirect, routing::get, Router}; use http::{HeaderMap, Request, Response}; use http_body_util::BodyExt; -use hyper::{http, service::service_fn}; +use http_mitm_proxy::MitmProxy; +use hyper::{ + body::{Body, Incoming}, + http, + service::{service_fn, HttpService}, +}; use hyper_util::rt::{TokioExecutor, TokioIo}; // Port 5111- is reserved for testing @@ -703,17 +710,82 @@ async fn test_unix_socket() { rx.try_recv().unwrap(); } +fn make_root_cert() -> rcgen::CertifiedKey { + let mut param = rcgen::CertificateParams::default(); + + param.distinguished_name = rcgen::DistinguishedName::new(); + param.distinguished_name.push( + rcgen::DnType::CommonName, + rcgen::DnValue::Utf8String("".to_string()), + ); + param.key_usages = vec![ + rcgen::KeyUsagePurpose::KeyCertSign, + rcgen::KeyUsagePurpose::CrlSign, + ]; + param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + + let key_pair = rcgen::KeyPair::generate().unwrap(); + let cert = param.self_signed(&key_pair).unwrap(); + + rcgen::CertifiedKey { cert, key_pair } +} + +async fn bind_proxy(service: S, http2: bool) -> (u16, impl Future) +where + S: HttpService + Clone + Send + 'static, + S::Error: Into>, + S::ResBody: Send + Sync + 'static, + ::Data: Send, + ::Error: Into>, + S::Future: Send, +{ + let port = PORT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + let tcp_listener = tokio::net::TcpListener::bind(("127.0.0.1", port)) + .await + .unwrap(); + + let cert = make_root_cert(); + let proxy = Arc::new(http_mitm_proxy::MitmProxy::new(Some(cert), None)); + + let serve = async move { + loop { + let (stream, _) = tcp_listener.accept().await.unwrap(); + + let proxy = proxy.clone(); + let service = service.clone(); + tokio::spawn(async move { + if http2 { + hyper::server::conn::http2::Builder::new(TokioExecutor::new()) + .serve_connection( + TokioIo::new(stream), + MitmProxy::wrap_service(proxy, service), + ) + .await + .unwrap(); + } else { + hyper::server::conn::http1::Builder::new() + .serve_connection( + TokioIo::new(stream), + MitmProxy::wrap_service(proxy, service), + ) + .await + .unwrap(); + } + }); + } + }; + + (port, serve) +} + #[tokio::test] -async fn test_proxy_http_http() { - let (tx, rx) = flume::unbounded(); - let (listener, port) = bind_port().await; - let proxy_port = PORT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); +async fn test_proxy_to_http() { + for http2 in [false, true] { + let (tx, rx) = flume::unbounded(); + let (listener, port) = bind_port().await; - let client = http_mitm_proxy::DefaultClient::new().unwrap(); - let proxy = http_mitm_proxy::MitmProxy::<&'static rcgen::CertifiedKey>::new(None, None); - let proxy_server = proxy - .bind( - ("127.0.0.1", proxy_port), + let client = http_mitm_proxy::DefaultClient::new().unwrap(); + let (proxy_port, proxy_server) = bind_proxy( service_fn(move |mut req| { let client = client.clone(); @@ -726,49 +798,52 @@ async fn test_proxy_http_http() { Ok::<_, http_mitm_proxy::default_client::Error>(res) } }), + http2, ) - .await - .unwrap(); - tokio::spawn(proxy_server); + .await; - tokio::spawn(async move { - loop { - let tx = tx.clone(); - let (tcp, _) = listener.accept().await.unwrap(); - hyper::server::conn::http1::Builder::new() - .serve_connection( - TokioIo::new(tcp), - service_fn(move |req| { - let tx = tx.clone(); + tokio::spawn(proxy_server); + tokio::spawn(async move { + loop { + let tx = tx.clone(); + let (tcp, _) = listener.accept().await.unwrap(); + hyper::server::conn::http1::Builder::new() + .serve_connection( + TokioIo::new(tcp), + service_fn(move |req| { + let tx = tx.clone(); - async move { - tx.send(req).unwrap(); - Ok::<_, Infallible>(Response::new("Hello World".to_string())) - } - }), - ) - .await - .unwrap(); - } - }); - tokio::task::spawn_blocking(move || { - Command::cargo_bin("oha") - .unwrap() - .args(["--no-tui", "--debug", "-x"]) - .arg(format!("http://127.0.0.1:{proxy_port}/")) - .arg(format!("http://127.0.0.1:{port}/")) - .assert() - .success(); - }) - .await - .unwrap(); + async move { + tx.send(req).unwrap(); + Ok::<_, Infallible>(Response::new("Hello World".to_string())) + } + }), + ) + .await + .unwrap(); + } + }); + + tokio::task::spawn_blocking(move || { + let mut p = Command::cargo_bin("oha").unwrap(); + p.args(["--no-tui", "--debug", "-x"]) + .arg(format!("http://127.0.0.1:{proxy_port}/")) + .arg(format!("http://127.0.0.1:{port}/")); + if http2 { + p.arg("--proxy-http2"); + } + p.assert().success(); + }) + .await + .unwrap(); - let req = rx.try_recv().unwrap(); + let req = rx.try_recv().unwrap(); - assert_eq!( - req.headers().get("x-oha-test-through-proxy").unwrap(), - "true" - ); + assert_eq!( + req.headers().get("x-oha-test-through-proxy").unwrap(), + "true" + ); + } } #[test] From 2b620e44eb8995e5ceb9d9ce9a3e7851fd2fc451 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 28 Nov 2024 21:40:28 +0900 Subject: [PATCH 15/24] test --- tests/tests.rs | 123 +++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index e6080006..91dbf18c 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -755,21 +755,22 @@ where let service = service.clone(); tokio::spawn(async move { if http2 { - hyper::server::conn::http2::Builder::new(TokioExecutor::new()) + let _ = hyper::server::conn::http2::Builder::new(TokioExecutor::new()) .serve_connection( TokioIo::new(stream), MitmProxy::wrap_service(proxy, service), ) - .await - .unwrap(); + .await; } else { - hyper::server::conn::http1::Builder::new() + let _ = hyper::server::conn::http1::Builder::new() + .preserve_header_case(true) + .title_case_headers(true) .serve_connection( TokioIo::new(stream), MitmProxy::wrap_service(proxy, service), ) - .await - .unwrap(); + .with_upgrades() + .await; } }); } @@ -779,70 +780,62 @@ where } #[tokio::test] -async fn test_proxy_to_http() { - for http2 in [false, true] { - let (tx, rx) = flume::unbounded(); - let (listener, port) = bind_port().await; - - let client = http_mitm_proxy::DefaultClient::new().unwrap(); - let (proxy_port, proxy_server) = bind_proxy( - service_fn(move |mut req| { - let client = client.clone(); - - async move { - req.headers_mut() - .insert("x-oha-test-through-proxy", "true".parse().unwrap()); - - let (res, _) = client.send_request(req).await?; +async fn test_proxy() { + for https in [false, true] { + for http2 in [false, true] { + for proxy_http2 in [ + false, // Currently, The test on proxy server on HTTP/2 will fail. + // I don't know this is a issue of either oha or http-mitm-proxy. + // But I think this is not a critical because the proxy server on HTTP/2 seems not common. + /*, true */ + ] { + let (tx, rx) = flume::unbounded(); + + let (proxy_port, proxy_serve) = bind_proxy( + service_fn(move |mut req| { + dbg!(&req); + let tx = tx.clone(); + async move { + req.headers_mut() + .insert("x-oha-test-through-proxy", "true".parse().unwrap()); - Ok::<_, http_mitm_proxy::default_client::Error>(res) - } - }), - http2, - ) - .await; + tx.send(req).unwrap(); - tokio::spawn(proxy_server); - tokio::spawn(async move { - loop { - let tx = tx.clone(); - let (tcp, _) = listener.accept().await.unwrap(); - hyper::server::conn::http1::Builder::new() - .serve_connection( - TokioIo::new(tcp), - service_fn(move |req| { - let tx = tx.clone(); + let res = Response::new("Hello World".to_string()); + Ok::<_, Infallible>(res) + } + }), + proxy_http2, + ) + .await; + + tokio::spawn(proxy_serve); + + tokio::task::spawn_blocking(move || { + let scheme = if https { "https" } else { "http" }; + let mut p = Command::cargo_bin("oha").unwrap(); + p.args(["--no-tui", "--debug", "--insecure", "-x"]) + .arg(format!("http://127.0.0.1:{proxy_port}/")) + .arg(format!("{scheme}://example.com/")); + if http2 { + p.arg("--http2"); + } + if proxy_http2 { + p.arg("--proxy-http2"); + } + dbg!(p.assert().success().get_output()); + }) + .await + .unwrap(); - async move { - tx.send(req).unwrap(); - Ok::<_, Infallible>(Response::new("Hello World".to_string())) - } - }), - ) - .await - .unwrap(); - } - }); + let req = rx.try_recv().unwrap(); - tokio::task::spawn_blocking(move || { - let mut p = Command::cargo_bin("oha").unwrap(); - p.args(["--no-tui", "--debug", "-x"]) - .arg(format!("http://127.0.0.1:{proxy_port}/")) - .arg(format!("http://127.0.0.1:{port}/")); - if http2 { - p.arg("--proxy-http2"); + assert_eq!( + req.headers().get("x-oha-test-through-proxy").unwrap(), + "true" + ); } - p.assert().success(); - }) - .await - .unwrap(); - - let req = rx.try_recv().unwrap(); - - assert_eq!( - req.headers().get("x-oha-test-through-proxy").unwrap(), - "true" - ); + } } } From f6341f06b93ea0bbd78fcfa84030776218d8d0cd Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 15:02:50 +0900 Subject: [PATCH 16/24] fix --- src/client.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/client.rs b/src/client.rs index 50099b67..d77c749f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -541,16 +541,20 @@ impl Client { #[inline] fn request(&self, url: &Url) -> Result>, ClientError> { + let use_proxy = self.proxy_url.is_some() && url.scheme() == "http"; + let mut builder = http::Request::builder() - .uri( - if self.is_http2() || (self.proxy_url.is_some() && url.scheme() == "http") { - &url[..] - } else { - &url[url::Position::BeforePath..] - }, - ) + .uri(if self.is_http2() || use_proxy { + &url[..] + } else { + &url[url::Position::BeforePath..] + }) .method(self.method.clone()) - .version(self.http_version); + .version(if use_proxy { + self.proxy_http_version + } else { + self.http_version + }); *builder .headers_mut() From 492e0b062674510cc63de2351bbdb7811c009783 Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 15:28:20 +0900 Subject: [PATCH 17/24] wip --- tests/tests.rs | 101 ++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 91dbf18c..56ace238 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -779,61 +779,60 @@ where (port, serve) } -#[tokio::test] -async fn test_proxy() { - for https in [false, true] { - for http2 in [false, true] { - for proxy_http2 in [ - false, // Currently, The test on proxy server on HTTP/2 will fail. - // I don't know this is a issue of either oha or http-mitm-proxy. - // But I think this is not a critical because the proxy server on HTTP/2 seems not common. - /*, true */ - ] { - let (tx, rx) = flume::unbounded(); - - let (proxy_port, proxy_serve) = bind_proxy( - service_fn(move |mut req| { - dbg!(&req); - let tx = tx.clone(); - async move { - req.headers_mut() - .insert("x-oha-test-through-proxy", "true".parse().unwrap()); +async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { + dbg!((https, http2, proxy_http2)); + let (tx, rx) = flume::unbounded(); - tx.send(req).unwrap(); + let (proxy_port, proxy_serve) = bind_proxy( + service_fn(move |mut req| { + let tx = tx.clone(); + async move { + req.headers_mut() + .insert("x-oha-test-through-proxy", "true".parse().unwrap()); - let res = Response::new("Hello World".to_string()); - Ok::<_, Infallible>(res) - } - }), - proxy_http2, - ) - .await; - - tokio::spawn(proxy_serve); - - tokio::task::spawn_blocking(move || { - let scheme = if https { "https" } else { "http" }; - let mut p = Command::cargo_bin("oha").unwrap(); - p.args(["--no-tui", "--debug", "--insecure", "-x"]) - .arg(format!("http://127.0.0.1:{proxy_port}/")) - .arg(format!("{scheme}://example.com/")); - if http2 { - p.arg("--http2"); - } - if proxy_http2 { - p.arg("--proxy-http2"); - } - dbg!(p.assert().success().get_output()); - }) - .await - .unwrap(); + tx.send(req).unwrap(); + + let res = Response::new("Hello World".to_string()); + Ok::<_, Infallible>(res) + } + }), + proxy_http2, + ) + .await; - let req = rx.try_recv().unwrap(); + tokio::spawn(proxy_serve); - assert_eq!( - req.headers().get("x-oha-test-through-proxy").unwrap(), - "true" - ); + tokio::task::spawn_blocking(move || { + let scheme = if https { "https" } else { "http" }; + let mut p = Command::cargo_bin("oha").unwrap(); + p.args(["--no-tui", "--debug", "--insecure", "-x"]) + .arg(format!("http://127.0.0.1:{proxy_port}/")) + .arg(format!("{scheme}://example.com/")); + if http2 { + p.arg("--http2"); + } + if proxy_http2 { + p.arg("--proxy-http2"); + } + p.assert().success() + }) + .await + .unwrap(); + + let req = rx.try_recv().unwrap(); + + assert_eq!( + req.headers().get("x-oha-test-through-proxy").unwrap(), + "true" + ); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn test_proxy() { + for https in [false, true] { + for http2 in [false, true] { + for proxy_http2 in [false, true] { + test_proxy_with_setting(https, http2, proxy_http2).await; } } } From 348250990ba99162fa06db74ae41c237c00b7d4d Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 15:34:40 +0900 Subject: [PATCH 18/24] a --- tests/tests.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 56ace238..e0d2f29f 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -814,10 +814,11 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { if proxy_http2 { p.arg("--proxy-http2"); } - p.assert().success() + p.timeout(std::time::Duration::from_secs(3)).assert() }) .await - .unwrap(); + .unwrap() + .success(); let req = rx.try_recv().unwrap(); From 1400ce429c17d74d9448ffd5b32bf68d5261fc28 Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 15:40:51 +0900 Subject: [PATCH 19/24] cargo update --- Cargo.lock | 430 +++++++++++++++++++++++++++++------------------------ 1 file changed, 233 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe599649..83254a60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,15 +251,15 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -272,9 +272,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -306,9 +306,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arrayvec" @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "aws-lc-fips-sys" -version = "0.12.13" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf12b67bc9c5168f68655aadb2a12081689a58f1d9b1484705e4d1810ed6e4ac" +checksum = "df1e8a8e212a7851ef3d4c28cdfc017072bc684f0e0f57c7943ab60f695c3bfb" dependencies = [ "bindgen", "cc", @@ -383,13 +383,12 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", - "mirai-annotations", "paste", "untrusted 0.7.1", "zeroize", @@ -397,9 +396,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" dependencies = [ "bindgen", "cc", @@ -412,9 +411,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -436,7 +435,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower", "tower-layer", @@ -459,7 +458,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -559,9 +558,9 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "borsh" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" dependencies = [ "borsh-derive", "cfg_aliases", @@ -569,16 +568,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.89", - "syn_derive", ] [[package]] @@ -604,9 +602,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "regex-automata", @@ -621,9 +619,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-unit" -version = "5.1.4" +version = "5.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ac19bdf0b2665407c39d82dbc937e951e7e2001609f0fb32edd0af45a2d63e" +checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174" dependencies = [ "rust_decimal", "serde", @@ -666,15 +664,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bytestring" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" dependencies = [ "bytes", ] @@ -696,9 +694,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.31" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -739,9 +737,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -749,9 +747,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -773,15 +771,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -833,6 +831,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -841,9 +849,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -916,6 +924,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.89", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.89", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -944,6 +987,12 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "difflib" version = "0.4.0" @@ -1036,12 +1085,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1069,15 +1118,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1333,9 +1382,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -1370,9 +1419,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -1417,7 +1466,7 @@ dependencies = [ "ipnet", "once_cell", "rand", - "thiserror 1.0.65", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -1440,7 +1489,7 @@ dependencies = [ "rand", "resolv-conf", "smallvec", - "thiserror 1.0.65", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -1552,14 +1601,14 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", + "h2 0.4.7", "http 1.1.0", "http-body", "httparse", @@ -1573,9 +1622,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1708,6 +1757,12 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.4.0" @@ -1720,24 +1775,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "idna" -version = "1.0.2" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd69211b9b519e98303c015e21a007e293db403b6c85b9b124e133d25e242cdd" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", - "smallvec", - "utf8_iter", ] [[package]] @@ -1753,7 +1807,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -1764,10 +1818,14 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "instability" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e" dependencies = [ + "darling", + "indoc", + "pretty_assertions", + "proc-macro2", "quote", "syn 2.0.89", ] @@ -1816,9 +1874,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jemalloc-sys" @@ -1860,9 +1918,9 @@ dependencies = [ [[package]] name = "jsonschema" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ae663abb3bb9e77538ee88a0eb69cbd3f62a8bf2018f848fbc60c2cdec024d" +checksum = "893d6229c7315763ca0df9b29ab7661ee419f286577a02847c5521b462e071af" dependencies = [ "ahash 0.8.11", "base64", @@ -1870,7 +1928,7 @@ dependencies = [ "email_address", "fancy-regex", "fraction", - "idna 1.0.2", + "idna 1.0.3", "itoa", "num-cmp", "once_cell", @@ -1903,9 +1961,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" [[package]] name = "libloading" @@ -1919,9 +1977,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsqlite3-sys" @@ -1948,9 +2006,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "local-channel" @@ -1991,7 +2049,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -2064,12 +2122,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "moka" version = "0.12.8" @@ -2085,7 +2137,7 @@ dependencies = [ "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.65", + "thiserror 1.0.69", "triomphe", "uuid", ] @@ -2111,7 +2163,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -2284,7 +2336,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror 1.0.65", + "thiserror 1.0.69", "tokio", "tokio-native-tls", "tokio-rustls", @@ -2456,6 +2508,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.25" @@ -2475,29 +2537,6 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.92" @@ -2677,9 +2716,9 @@ dependencies = [ [[package]] name = "referencing" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c152a23ee0e5947ee31d9cfebc873a5aa3a249da9e59d2e76cd7416a13cc9a5d" +checksum = "eb853437e467c693ac1dc8c1520105a31b8c2588544ff2f3cfa5a7c706c6c069" dependencies = [ "ahash 0.8.11", "fluent-uri", @@ -2702,9 +2741,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2734,9 +2773,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64", "bytes", @@ -2758,7 +2797,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower-service", "url", @@ -2884,9 +2923,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags", "errno", @@ -2897,9 +2936,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "aws-lc-rs", "log", @@ -2912,24 +2951,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", + "security-framework 3.0.1", ] [[package]] @@ -2964,9 +2993,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -2990,7 +3019,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -2998,9 +3040,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -3014,18 +3056,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -3034,9 +3076,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3136,9 +3178,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3221,18 +3263,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.89", -] - [[package]] name = "sync_wrapper" version = "0.1.2" @@ -3241,9 +3271,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -3273,9 +3303,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -3292,11 +3322,11 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.65", + "thiserror-impl 1.0.69", ] [[package]] @@ -3310,9 +3340,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -3388,9 +3418,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3509,9 +3539,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -3521,9 +3551,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -3532,9 +3562,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -3565,9 +3595,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -3621,12 +3651,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", ] @@ -4061,6 +4091,12 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yasna" version = "0.5.2" @@ -4072,9 +4108,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -4084,9 +4120,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", @@ -4117,18 +4153,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", From 442cbed5e01c6786841ff4d74ba1d6cf0a94a69b Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 15:49:33 +0900 Subject: [PATCH 20/24] a --- tests/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.rs b/tests/tests.rs index e0d2f29f..cfee6020 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -814,7 +814,7 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { if proxy_http2 { p.arg("--proxy-http2"); } - p.timeout(std::time::Duration::from_secs(3)).assert() + p.assert() }) .await .unwrap() From 4c47f8321636014cb38906eaaa4eba74b935e712 Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 16:03:54 +0900 Subject: [PATCH 21/24] wip --- tests/tests.rs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index cfee6020..78128d4b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -802,23 +802,25 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { tokio::spawn(proxy_serve); - tokio::task::spawn_blocking(move || { - let scheme = if https { "https" } else { "http" }; - let mut p = Command::cargo_bin("oha").unwrap(); - p.args(["--no-tui", "--debug", "--insecure", "-x"]) - .arg(format!("http://127.0.0.1:{proxy_port}/")) - .arg(format!("{scheme}://example.com/")); - if http2 { - p.arg("--http2"); - } - if proxy_http2 { - p.arg("--proxy-http2"); - } - p.assert() - }) - .await - .unwrap() - .success(); + let cargo_bin = Command::cargo_bin("oha").unwrap(); + let mut proc = tokio::process::Command::new(cargo_bin.get_program()); + std::mem::drop(cargo_bin); + + let scheme = if https { "https" } else { "http" }; + proc.args(["--no-tui", "--debug", "--insecure", "-x"]) + .arg(format!("http://127.0.0.1:{proxy_port}/")) + .arg(format!("{scheme}://example.com/")); + if http2 { + proc.arg("--http2"); + } + if proxy_http2 { + proc.arg("--proxy-http2"); + } + + proc.stdin(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()); + proc.spawn().unwrap().wait().await.unwrap(); let req = rx.try_recv().unwrap(); @@ -828,7 +830,7 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { ); } -#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +#[tokio::test] async fn test_proxy() { for https in [false, true] { for http2 in [false, true] { From 0136b9e832b30347c8b16873f946ac26fcc9b38f Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 16:42:00 +0900 Subject: [PATCH 22/24] a --- tests/tests.rs | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 78128d4b..d29f1a9a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -781,20 +781,11 @@ where async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { dbg!((https, http2, proxy_http2)); - let (tx, rx) = flume::unbounded(); let (proxy_port, proxy_serve) = bind_proxy( - service_fn(move |mut req| { - let tx = tx.clone(); - async move { - req.headers_mut() - .insert("x-oha-test-through-proxy", "true".parse().unwrap()); - - tx.send(req).unwrap(); - - let res = Response::new("Hello World".to_string()); - Ok::<_, Infallible>(res) - } + service_fn(|_req| async { + let res = Response::new("Hello World".to_string()); + Ok::<_, Infallible>(res) }), proxy_http2, ) @@ -818,23 +809,24 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { } proc.stdin(std::process::Stdio::null()) - .stdout(std::process::Stdio::null()) + .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::null()); - proc.spawn().unwrap().wait().await.unwrap(); - - let req = rx.try_recv().unwrap(); + let stdout = proc + .spawn() + .unwrap() + .wait_with_output() + .await + .unwrap() + .stdout; - assert_eq!( - req.headers().get("x-oha-test-through-proxy").unwrap(), - "true" - ); + assert!(String::from_utf8(stdout).unwrap().contains("Hello World"),); } -#[tokio::test] +#[tokio::test(flavor = "multi_thread", worker_threads = 64)] async fn test_proxy() { for https in [false, true] { for http2 in [false, true] { - for proxy_http2 in [false, true] { + for proxy_http2 in [false] { test_proxy_with_setting(https, http2, proxy_http2).await; } } From 86e1b309aa82edf2a13962c6832ed2473dbebcf8 Mon Sep 17 00:00:00 2001 From: hatoo Date: Fri, 29 Nov 2024 16:58:02 +0900 Subject: [PATCH 23/24] fix test --- tests/tests.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index d29f1a9a..c51e847c 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -822,11 +822,15 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { assert!(String::from_utf8(stdout).unwrap().contains("Hello World"),); } -#[tokio::test(flavor = "multi_thread", worker_threads = 64)] +#[tokio::test] async fn test_proxy() { for https in [false, true] { for http2 in [false, true] { - for proxy_http2 in [false] { + for proxy_http2 in [ + false, + // true + // Skip Proxy server on HTTP/2 beacause it's buggy on httm-mitm-proxy + ] { test_proxy_with_setting(https, http2, proxy_http2).await; } } From 08db9b4352bae74c0729dbb2555033c71997c476 Mon Sep 17 00:00:00 2001 From: hatoo Date: Thu, 5 Dec 2024 17:26:58 +0900 Subject: [PATCH 24/24] test ok --- Cargo.toml | 5 +++++ tests/tests.rs | 12 +++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6936386a..2dc31df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,3 +104,8 @@ lto = true debug = false incremental = false overflow-checks = false + +# For full test on proxy +# See test_proxy() on tests/proxy.rs +# [patch.crates-io] +# tokio-rustls = { git = "https://github.com/rustls/tokio-rustls" } diff --git a/tests/tests.rs b/tests/tests.rs index c51e847c..18c315ab 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -780,8 +780,6 @@ where } async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { - dbg!((https, http2, proxy_http2)); - let (proxy_port, proxy_serve) = bind_proxy( service_fn(|_req| async { let res = Response::new("Hello World".to_string()); @@ -826,11 +824,11 @@ async fn test_proxy_with_setting(https: bool, http2: bool, proxy_http2: bool) { async fn test_proxy() { for https in [false, true] { for http2 in [false, true] { - for proxy_http2 in [ - false, - // true - // Skip Proxy server on HTTP/2 beacause it's buggy on httm-mitm-proxy - ] { + for proxy_http2 in [false, true] { + if https && proxy_http2 { + // Waiting for https://github.com/rustls/tokio-rustls/pull/93 is released + continue; + } test_proxy_with_setting(https, http2, proxy_http2).await; } }