From e15bea78baa0f553597ba3cda9cab359976f9657 Mon Sep 17 00:00:00 2001 From: Nikolai Golub Date: Tue, 9 Jun 2026 12:21:24 +0200 Subject: [PATCH 1/4] Add support for connection_timeout --- CHANGELOG.md | 6 ++++++ client/http-client/src/client.rs | 17 ++++++++++++++++ client/http-client/src/tests.rs | 30 +++++++++++++++++++++++++++++ client/http-client/src/transport.rs | 7 +++++++ 4 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2902880b05..38e6d3b072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ The format is based on [Keep a Changelog]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ +## [Unreleased] + +### [Added] + +- feat(http-client): expose connect timeout option ([#XXXX](https://github.com/paritytech/jsonrpsee/pull/XXXX)) + ## [v0.26.0] - 2025-08-11 This is just a small release; the only breaking change is the addition of `max_frame_size` to `WsTransportClientBuilder`, which necessitates a minor version bump. diff --git a/client/http-client/src/client.rs b/client/http-client/src/client.rs index 81466914e5..ecd9af75fa 100644 --- a/client/http-client/src/client.rs +++ b/client/http-client/src/client.rs @@ -82,6 +82,7 @@ pub struct HttpClientBuilder max_request_size: u32, max_response_size: u32, request_timeout: Duration, + connect_timeout: Option, #[cfg(feature = "tls")] certificate_store: CertificateStore, id_kind: IdKind, @@ -114,6 +115,17 @@ impl HttpClientBuilder Self { + self.connect_timeout = Some(timeout); + self + } + /// Set the maximum number of concurrent requests. Default disabled. pub fn max_concurrent_requests(mut self, max_concurrent_requests: usize) -> Self { self.max_concurrent_requests = Some(max_concurrent_requests); @@ -248,6 +260,7 @@ impl HttpClientBuilder HttpClientBuilder("say_hello", rpc_params![]), + ) + .await + .expect("connect should fail well before the request timeout"); + + match res { + Ok(_) => panic!("expected a connect error, got a successful response"), + Err(ClientError::RequestTimeout) => panic!("request failed via the request timeout, not the connect timeout"), + Err(_) => {} + } +} + #[tokio::test] async fn method_call_with_wrong_id_kind() { let exp = "id as string"; diff --git a/client/http-client/src/transport.rs b/client/http-client/src/transport.rs index 5379cc95c0..00f37b28e7 100644 --- a/client/http-client/src/transport.rs +++ b/client/http-client/src/transport.rs @@ -104,6 +104,8 @@ pub struct HttpTransportClientBuilder { pub(crate) keep_alive_interval: Option, /// KEEP_ALIVE retries pub(crate) keep_alive_retries: Option, + /// TCP connect timeout + pub(crate) connect_timeout: Option, } impl Default for HttpTransportClientBuilder { @@ -126,6 +128,7 @@ impl HttpTransportClientBuilder { keep_alive_duration: None, keep_alive_interval: None, keep_alive_retries: None, + connect_timeout: None, } } } @@ -197,6 +200,7 @@ impl HttpTransportClientBuilder { keep_alive_duration: self.keep_alive_duration, keep_alive_retries: self.keep_alive_retries, keep_alive_interval: self.keep_alive_interval, + connect_timeout: self.connect_timeout, } } @@ -220,6 +224,7 @@ impl HttpTransportClientBuilder { keep_alive_duration, keep_alive_interval, keep_alive_retries, + connect_timeout, } = self; let mut url = Url::parse(target.as_ref()).map_err(|e| Error::Url(format!("Invalid URL: {e}")))?; @@ -235,6 +240,7 @@ impl HttpTransportClientBuilder { connector.set_keepalive(keep_alive_duration); connector.set_keepalive_interval(keep_alive_interval); connector.set_keepalive_retries(keep_alive_retries); + connector.set_connect_timeout(connect_timeout); HttpBackend::Http(Client::builder(TokioExecutor::new()).build(connector)) } #[cfg(feature = "tls")] @@ -251,6 +257,7 @@ impl HttpTransportClientBuilder { http_conn.set_keepalive(keep_alive_duration); http_conn.set_keepalive_interval(keep_alive_interval); http_conn.set_keepalive_retries(keep_alive_retries); + http_conn.set_connect_timeout(connect_timeout); let https_conn = match certificate_store { CertificateStore::Native => { From fd6c0af408e4a8503bf7bba7a2503b368255b883 Mon Sep 17 00:00:00 2001 From: Nikolai Golub Date: Tue, 9 Jun 2026 12:22:47 +0200 Subject: [PATCH 2/4] Add CHANGELOG.md entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e6d3b072..0586ddadca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The format is based on [Keep a Changelog]. ### [Added] -- feat(http-client): expose connect timeout option ([#XXXX](https://github.com/paritytech/jsonrpsee/pull/XXXX)) +- feat(http-client): expose connect timeout option ([#1643](https://github.com/paritytech/jsonrpsee/pull/1643)) ## [v0.26.0] - 2025-08-11 From 2b1b59535c5787327764e19df7885edc7fa19b34 Mon Sep 17 00:00:00 2001 From: Nikolai Golub Date: Wed, 10 Jun 2026 16:23:56 +0200 Subject: [PATCH 3/4] cargo fmt --- client/http-client/src/tests.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/http-client/src/tests.rs b/client/http-client/src/tests.rs index 61f67353d5..2d020a6a5d 100644 --- a/client/http-client/src/tests.rs +++ b/client/http-client/src/tests.rs @@ -67,12 +67,9 @@ async fn connect_timeout_fires_before_request_timeout() { // Bound the test well under the 60s request timeout: the connect should fail in ~100ms. If it // regressed and hung until the request timeout, this outer 10s bound trips and fails the test. - let res = tokio::time::timeout( - Duration::from_secs(10), - client.request::("say_hello", rpc_params![]), - ) - .await - .expect("connect should fail well before the request timeout"); + let res = tokio::time::timeout(Duration::from_secs(10), client.request::("say_hello", rpc_params![])) + .await + .expect("connect should fail well before the request timeout"); match res { Ok(_) => panic!("expected a connect error, got a successful response"), From 688628441e03a3919bac241b1b3d52be8da29af6 Mon Sep 17 00:00:00 2001 From: Nikolai Golub Date: Thu, 30 Jul 2026 09:11:00 +0200 Subject: [PATCH 4/4] Allow setting tcp connect timeout on Http builder too --- client/http-client/src/transport.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/http-client/src/transport.rs b/client/http-client/src/transport.rs index 00f37b28e7..8226758f4b 100644 --- a/client/http-client/src/transport.rs +++ b/client/http-client/src/transport.rs @@ -175,6 +175,12 @@ impl HttpTransportClientBuilder { self } + /// Configure the TCP connect timeout for the connection. + pub fn set_connect_timeout(mut self, timeout: Option) -> Self { + self.connect_timeout = timeout; + self + } + /// Configure the keep-alive interval for the connection. pub fn set_keep_alive_interval(mut self, interval: Option) -> Self { self.keep_alive_interval = interval;