]> Untitled Git - bdk/commitdiff
[esplora] Support proxies in EsploraBlockchain
authorAlekos Filini <alekos.filini@gmail.com>
Mon, 30 Aug 2021 13:49:07 +0000 (15:49 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Thu, 23 Sep 2021 19:38:19 +0000 (21:38 +0200)
CHANGELOG.md
Cargo.toml
src/blockchain/esplora/reqwest.rs
src/blockchain/esplora/ureq.rs

index 90805b0ceba1bd5e6d82bb48d9cc99da76e67dbd..f179e6540e21535be0c706b939c3ee482b0d2799 100644 (file)
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [v0.11.0] - [v0.10.0]
 
 - Added `flush` method to the `Database` trait to explicitly flush to disk latest changes on the db.
+- Add support for proxies in `EsploraBlockchain`
 
 ## [v0.10.0] - [v0.9.0]
 
index e4d7c8c5584e1010c181d9e508b016266a39d201..efc402e220ce4b5a060c3eb957d0914602ea5122 100644 (file)
@@ -77,8 +77,8 @@ rpc = ["core-rpc"]
 async-interface = ["async-trait"]
 electrum = ["electrum-client"]
 # MUST ALSO USE `--no-default-features`.
-use-esplora-reqwest = ["esplora", "reqwest", "futures"]
-use-esplora-ureq = ["esplora", "ureq"]
+use-esplora-reqwest = ["esplora", "reqwest", "reqwest/socks", "futures"]
+use-esplora-ureq = ["esplora", "ureq", "ureq/socks"]
 # Typical configurations will not need to use `esplora` feature directly.
 esplora = []
 
index 528fb7adc09b30a06bc935baec75bf8f6e4ea3ce..6e9c7aad908b86ac33cb7bac19934c6387a29e32 100644 (file)
@@ -333,6 +333,17 @@ pub struct EsploraBlockchainConfig {
     ///
     /// eg. `https://blockstream.info/api/`
     pub base_url: String,
+    /// Optional URL of the proxy to use to make requests to the Esplora server
+    ///
+    /// The string should be formatted as: `<protocol>://<user>:<password>@host:<port>`.
+    ///
+    /// Note that the format of this value and the supported protocols change slightly between the
+    /// sync version of esplora (using `ureq`) and the async version (using `reqwest`). For more
+    /// details check with the documentation of the two crates. Both of them are compiled with
+    /// the `socks` feature enabled.
+    ///
+    /// The proxy is ignored when targeting `wasm32`.
+    pub proxy: Option<String>,
     /// Number of parallel requests sent to the esplora service (default: 4)
     pub concurrency: Option<u8>,
     /// Stop searching addresses for transactions after finding an unused gap of this length.
@@ -343,10 +354,19 @@ impl ConfigurableBlockchain for EsploraBlockchain {
     type Config = EsploraBlockchainConfig;
 
     fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let map_e = |e: reqwest::Error| Error::Esplora(Box::new(e.into()));
+
         let mut blockchain = EsploraBlockchain::new(config.base_url.as_str(), config.stop_gap);
         if let Some(concurrency) = config.concurrency {
             blockchain.url_client.concurrency = concurrency;
-        };
+        }
+        #[cfg(not(target_arch = "wasm32"))]
+        if let Some(proxy) = &config.proxy {
+            blockchain.url_client.client = Client::builder()
+                .proxy(reqwest::Proxy::all(proxy).map_err(map_e)?)
+                .build()
+                .map_err(map_e)?;
+        }
         Ok(blockchain)
     }
 }
index 24a37e865dc525ac73f57fbb0e968837c639ff75..177b773d65b54ef6930ed57f03b3ef7a1750fd09 100644 (file)
@@ -19,7 +19,7 @@ use std::time::Duration;
 #[allow(unused_imports)]
 use log::{debug, error, info, trace};
 
-use ureq::{Agent, Response};
+use ureq::{Agent, Proxy, Response};
 
 use bitcoin::consensus::{deserialize, serialize};
 use bitcoin::hashes::hex::{FromHex, ToHex};
@@ -59,7 +59,7 @@ impl std::convert::From<UrlClient> for EsploraBlockchain {
 }
 
 impl EsploraBlockchain {
-    /// Create a new instance of the client from a base URL and `stop_gap`.
+    /// Create a new instance of the client from a base URL and the `stop_gap`.
     pub fn new(base_url: &str, stop_gap: usize) -> Self {
         EsploraBlockchain {
             url_client: UrlClient {
@@ -358,6 +358,17 @@ impl ElectrumLikeSync for UrlClient {
 pub struct EsploraBlockchainConfig {
     /// Base URL of the esplora service eg. `https://blockstream.info/api/`
     pub base_url: String,
+    /// Optional URL of the proxy to use to make requests to the Esplora server
+    ///
+    /// The string should be formatted as: `<protocol>://<user>:<password>@host:<port>`.
+    ///
+    /// Note that the format of this value and the supported protocols change slightly between the
+    /// sync version of esplora (using `ureq`) and the async version (using `reqwest`). For more
+    /// details check with the documentation of the two crates. Both of them are compiled with
+    /// the `socks` feature enabled.
+    ///
+    /// The proxy is ignored when targeting `wasm32`.
+    pub proxy: Option<String>,
     /// Socket read timeout.
     pub timeout_read: u64,
     /// Socket write timeout.
@@ -370,10 +381,18 @@ impl ConfigurableBlockchain for EsploraBlockchain {
     type Config = EsploraBlockchainConfig;
 
     fn from_config(config: &Self::Config) -> Result<Self, Error> {
-        let agent: Agent = ureq::AgentBuilder::new()
+        let mut agent_builder = ureq::AgentBuilder::new()
             .timeout_read(Duration::from_secs(config.timeout_read))
-            .timeout_write(Duration::from_secs(config.timeout_write))
-            .build();
-        Ok(EsploraBlockchain::new(config.base_url.as_str(), config.stop_gap).with_agent(agent))
+            .timeout_write(Duration::from_secs(config.timeout_write));
+
+        if let Some(proxy) = &config.proxy {
+            agent_builder = agent_builder
+                .proxy(Proxy::new(proxy).map_err(|e| Error::Esplora(Box::new(e.into())))?);
+        }
+
+        Ok(
+            EsploraBlockchain::new(config.base_url.as_str(), config.stop_gap)
+                .with_agent(agent_builder.build()),
+        )
     }
 }