From d177d18028e13a094c2c1f91ce26dfe33ad5f1de Mon Sep 17 00:00:00 2001 From: Rakan Alhneiti Date: Wed, 24 Sep 2025 20:23:05 +0300 Subject: [PATCH 1/2] Add constructor with timeouts --- client/src/client.rs | 26 ++++++++++++++++++++++++++ client/src/transport.rs | 25 ++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/client/src/client.rs b/client/src/client.rs index 39402e92..ddc6e6ff 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -1366,6 +1366,32 @@ impl Client { client, }) } + + /// Creates a client to a bitcoind JSON-RPC server with custom timeout configuration. + pub async fn with_timeouts( + url: &str, + auth: Auth, + timeout: Duration, + connect_timeout: Option, + ) -> Result { + let mut parsed_url = Url::parse(url)?; + + if let (Some(user), pass) = auth.get_user_pass()? { + parsed_url + .set_username(&user) + .map_err(|_| Error::Auth("Failed to set username".to_string()))?; + parsed_url + .set_password(pass.as_deref()) + .map_err(|_| Error::Auth("Failed to set password".to_string()))?; + } + + let transport = ReqwestTransport::with_timeouts(parsed_url, timeout, connect_timeout); + let client = JsonRpcClient::with_transport(transport); + + Ok(Self { + client, + }) + } } #[async_trait] diff --git a/client/src/transport.rs b/client/src/transport.rs index 81b5ab3c..0489a36c 100644 --- a/client/src/transport.rs +++ b/client/src/transport.rs @@ -1,7 +1,10 @@ use async_trait::async_trait; use jsonrpc_async::Transport; +use std::time::Duration; use url::Url; +const DEFAULT_TIMEOUT: Duration = Duration::from_secs(15); + pub struct ReqwestTransport { client: reqwest::Client, url: Url, @@ -9,8 +12,28 @@ pub struct ReqwestTransport { impl ReqwestTransport { pub fn new(url: Url) -> Self { + let client = reqwest::Client::builder() + .timeout(DEFAULT_TIMEOUT) + .build() + .expect("Failed to build reqwest client"); + + Self { + client, + url, + } + } + + pub fn with_timeouts(url: Url, timeout: Duration, connect_timeout: Option) -> Self { + let mut builder = reqwest::Client::builder().timeout(timeout); + + if let Some(connect_timeout) = connect_timeout { + builder = builder.connect_timeout(connect_timeout); + } + + let client = builder.build().expect("Failed to build reqwest client"); + Self { - client: reqwest::Client::new(), + client, url, } } From a6e011abec5e345c6474dd47a0b58fd93d486193 Mon Sep 17 00:00:00 2001 From: Rakan Alhneiti Date: Wed, 24 Sep 2025 20:38:32 +0300 Subject: [PATCH 2/2] Make timeouts optional, unwrap or default --- client/src/client.rs | 2 +- client/src/transport.rs | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index ddc6e6ff..8a67f84b 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -1371,7 +1371,7 @@ impl Client { pub async fn with_timeouts( url: &str, auth: Auth, - timeout: Duration, + timeout: Option, connect_timeout: Option, ) -> Result { let mut parsed_url = Url::parse(url)?; diff --git a/client/src/transport.rs b/client/src/transport.rs index 0489a36c..ad3818bc 100644 --- a/client/src/transport.rs +++ b/client/src/transport.rs @@ -23,12 +23,14 @@ impl ReqwestTransport { } } - pub fn with_timeouts(url: Url, timeout: Duration, connect_timeout: Option) -> Self { - let mut builder = reqwest::Client::builder().timeout(timeout); - - if let Some(connect_timeout) = connect_timeout { - builder = builder.connect_timeout(connect_timeout); - } + pub fn with_timeouts( + url: Url, + timeout: Option, + connect_timeout: Option, + ) -> Self { + let builder = reqwest::Client::builder() + .timeout(timeout.unwrap_or(DEFAULT_TIMEOUT)) + .connect_timeout(connect_timeout.unwrap_or(DEFAULT_TIMEOUT)); let client = builder.build().expect("Failed to build reqwest client");