From 15ed547722bdab21a2c598bf66dbf2209068ed86 Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 14:06:34 +0100 Subject: [PATCH 01/10] Added basic and bearer authentication for http and websocket transport --- Cargo.lock | 2 ++ ethers-providers/Cargo.toml | 4 ++- ethers-providers/src/transports/common.rs | 9 +++++ ethers-providers/src/transports/http.rs | 42 ++++++++++++++++++++--- ethers-providers/src/transports/mod.rs | 3 +- ethers-providers/src/transports/ws.rs | 26 ++++++++++++++ 6 files changed, 79 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84654357b..9e35b0198 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1274,6 +1274,7 @@ version = "0.6.0" dependencies = [ "async-trait", "auto_impl", + "base64 0.13.0", "bytes", "ethers-core", "futures-channel", @@ -1281,6 +1282,7 @@ dependencies = [ "futures-timer", "futures-util", "hex", + "http", "parking_lot", "pin-project", "reqwest", diff --git a/ethers-providers/Cargo.toml b/ethers-providers/Cargo.toml index b68d06527..b4d63e3db 100644 --- a/ethers-providers/Cargo.toml +++ b/ethers-providers/Cargo.toml @@ -24,6 +24,8 @@ serde_json = { version = "1.0.64", default-features = false } thiserror = { version = "1.0.30", default-features = false } url = { version = "2.2.2", default-features = false } auto_impl = { version = "0.5.0", default-features = false } +http = { version = "0.2", optional = true } +base64 = { version = "0.13", optional = true } # required for implementing stream on the filters futures-core = { version = "0.3.16", default-features = false } @@ -60,7 +62,7 @@ tempfile = "3.3.0" [features] default = ["ws", "rustls"] celo = ["ethers-core/celo"] -ws = ["tokio", "tokio-tungstenite"] +ws = ["tokio", "tokio-tungstenite", "http", "base64"] ipc = ["tokio", "tokio/io-util", "tokio-util", "bytes"] openssl = ["tokio-tungstenite/native-tls", "reqwest/native-tls"] diff --git a/ethers-providers/src/transports/common.rs b/ethers-providers/src/transports/common.rs index 29917b766..fec4be08a 100644 --- a/ethers-providers/src/transports/common.rs +++ b/ethers-providers/src/transports/common.rs @@ -94,6 +94,15 @@ impl ResponseData { } } +/// Basic or bearer authentication in http or websocket transport +/// +/// Use to inject username and password or an auth token into requests +#[derive(Clone, Debug)] +pub enum Authorization { + Basic(String, String), + Bearer(String), +} + #[cfg(test)] mod tests { use super::*; diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index 3db8d2f29..d50719ebd 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -11,7 +11,7 @@ use std::{ use thiserror::Error; use url::Url; -use super::common::{JsonRpcError, Request, Response}; +use super::common::{Authorization, JsonRpcError, Request, Response}; /// A low-level JSON-RPC Client over HTTP. /// @@ -33,6 +33,7 @@ pub struct Provider { id: AtomicU64, client: Client, url: Url, + authorization: Option, } #[derive(Error, Debug)] @@ -69,10 +70,19 @@ impl JsonRpcClient for Provider { params: T, ) -> Result { let next_id = self.id.fetch_add(1, Ordering::SeqCst); - let payload = Request::new(next_id, method, params); - let res = self.client.post(self.url.as_ref()).json(&payload).send().await?; + let mut client = self.client.post(self.url.as_ref()).json(&payload); + if let Some(auth) = &self.authorization { + client = match auth { + Authorization::Basic(username, password) => { + client.basic_auth(username, Some(password)) + } + Authorization::Bearer(token) => client.bearer_auth(token), + }; + } + + let res = client.send().await?; let text = res.text().await?; let res: Response = serde_json::from_str(&text).map_err(|err| ClientError::SerdeJson { err, text })?; @@ -94,7 +104,24 @@ impl Provider { /// let provider = Http::new(url); /// ``` pub fn new(url: impl Into) -> Self { - Self { id: AtomicU64::new(0), client: Client::new(), url: url.into() } + Self { id: AtomicU64::new(0), client: Client::new(), url: url.into(), authorization: None } + } + + /// Initializes a new HTTP Client with authentication + /// + /// # Example + /// + /// ``` + /// use ethers_providers::{Http, Auth}; + /// use url::Url; + /// + /// let url = Url::parse("http://localhost:8545").unwrap(); + /// let provider = Http::new(url, Auth::Basic("admin", "good_password")); + /// ``` + pub fn new_with_auth(url: impl Into, auth: Authorization) -> Self { + let mut provider = Self::new(url); + provider.authorization = Some(auth); + provider } } @@ -109,6 +136,11 @@ impl FromStr for Provider { impl Clone for Provider { fn clone(&self) -> Self { - Self { id: AtomicU64::new(0), client: self.client.clone(), url: self.url.clone() } + Self { + id: AtomicU64::new(0), + client: self.client.clone(), + url: self.url.clone(), + authorization: None, + } } } diff --git a/ethers-providers/src/transports/mod.rs b/ethers-providers/src/transports/mod.rs index 1c714eac1..b7a6c64e6 100644 --- a/ethers-providers/src/transports/mod.rs +++ b/ethers-providers/src/transports/mod.rs @@ -1,4 +1,5 @@ mod common; +pub use common::Authorization; // only used with WS #[cfg(feature = "ws")] @@ -24,7 +25,7 @@ mod ipc; pub use ipc::Ipc; mod http; -pub use http::{ClientError as HttpClientError, Provider as Http}; +pub use self::http::{ClientError as HttpClientError, Provider as Http}; #[cfg(feature = "ws")] mod ws; diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index 44df77d1e..00ab4d2e8 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -5,12 +5,14 @@ use crate::{ }; use ethers_core::types::U256; +use super::Authorization; use async_trait::async_trait; use futures_channel::{mpsc, oneshot}; use futures_util::{ sink::{Sink, SinkExt}, stream::{Fuse, Stream, StreamExt}, }; +use http::Request as HttpRequest; use serde::{de::DeserializeOwned, Serialize}; use std::{ collections::{btree_map::Entry, BTreeMap}, @@ -140,6 +142,25 @@ impl Ws { Ok(Self::new(ws)) } + /// Initializes a new WebSocket Client with authentication + #[cfg(not(target_arch = "wasm32"))] + pub async fn connect_with_auth( + url: impl Into> + Unpin, + auth: Authorization, + ) -> Result { + let mut request: HttpRequest<()> = url.into(); + let auth_header = match auth { + Authorization::Basic(username, password) => { + String::from("Basic ") + base64::encode(username + ":" + &password).as_str() + } + Authorization::Bearer(token) => String::from("Bearer ") + &token, + }; + request + .headers_mut() + .insert(http::header::AUTHORIZATION, http::HeaderValue::from_str(&auth_header)?); + Self::connect(request).await + } + fn send(&self, msg: Instruction) -> Result<(), ClientError> { self.instructions.unbounded_send(msg).map_err(to_client_error) } @@ -442,6 +463,11 @@ pub enum ClientError { /// Something caused the websocket to close #[error("WebSocket connection closed unexpectedly")] UnexpectedClose, + + /// Could not create an auth header for websocket handshake + #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] + WsAuth(#[from] http::header::InvalidHeaderValue), } impl From for ProviderError { From f2fb01b2d6a135db988c4d65366293a88b805e27 Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 17:26:55 +0100 Subject: [PATCH 02/10] Improved api for websocket `connect_with_auth` --- ethers-providers/src/transports/ws.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index 00ab4d2e8..c956c3ce9 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -12,7 +12,6 @@ use futures_util::{ sink::{Sink, SinkExt}, stream::{Fuse, Stream, StreamExt}, }; -use http::Request as HttpRequest; use serde::{de::DeserializeOwned, Serialize}; use std::{ collections::{btree_map::Entry, BTreeMap}, @@ -62,6 +61,9 @@ if_not_wasm! { type WsError = tungstenite::Error; type WsStreamItem = Result; use tracing::{debug, error, warn}; + use http::Request as HttpRequest; + use http::Uri; + use std::str::FromStr; } type Pending = oneshot::Sender>; @@ -145,10 +147,11 @@ impl Ws { /// Initializes a new WebSocket Client with authentication #[cfg(not(target_arch = "wasm32"))] pub async fn connect_with_auth( - url: impl Into> + Unpin, + uri: impl AsRef + Unpin, auth: Authorization, ) -> Result { - let mut request: HttpRequest<()> = url.into(); + let mut request: HttpRequest<()> = + HttpRequest::builder().method("GET").uri(Uri::from_str(uri.as_ref())?).body(())?; let auth_header = match auth { Authorization::Basic(username, password) => { String::from("Basic ") + base64::encode(username + ":" + &password).as_str() @@ -468,6 +471,16 @@ pub enum ClientError { #[error(transparent)] #[cfg(not(target_arch = "wasm32"))] WsAuth(#[from] http::header::InvalidHeaderValue), + + /// Unable to create a valid Uri + #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] + UriError(#[from] http::uri::InvalidUri), + + /// Unable to create a valid Request + #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] + RequestError(#[from] http::Error), } impl From for ProviderError { From 225666ba1750fbfdb3300b0f2aed460df41e2acf Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 17:50:27 +0100 Subject: [PATCH 03/10] Bugfix in doc --- ethers-providers/src/transports/http.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index d50719ebd..b8a81e6e8 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -116,7 +116,7 @@ impl Provider { /// use url::Url; /// /// let url = Url::parse("http://localhost:8545").unwrap(); - /// let provider = Http::new(url, Auth::Basic("admin", "good_password")); + /// let provider = Http::new_with_auth(url, Auth::Basic("admin", "good_password")); /// ``` pub fn new_with_auth(url: impl Into, auth: Authorization) -> Self { let mut provider = Self::new(url); From 18501a69c66d118a09a04f18594150ff6f47c9bd Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 17:54:50 +0100 Subject: [PATCH 04/10] Moved use statement into non-wasm imports --- ethers-providers/src/transports/ws.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index c956c3ce9..5ee10a23c 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -5,7 +5,6 @@ use crate::{ }; use ethers_core::types::U256; -use super::Authorization; use async_trait::async_trait; use futures_channel::{mpsc, oneshot}; use futures_util::{ @@ -60,6 +59,7 @@ if_not_wasm! { type Message = tungstenite::protocol::Message; type WsError = tungstenite::Error; type WsStreamItem = Result; + use super::Authorization; use tracing::{debug, error, warn}; use http::Request as HttpRequest; use http::Uri; From b70923ebe40a7c8eba51bfc64a54e2061d64efb3 Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 18:29:56 +0100 Subject: [PATCH 05/10] Adapted changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10f1d6fbb..52b185ff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,8 @@ [640](https://github.com/gakonst/ethers-rs/pull/640) ### Unreleased +- Add support for basic and bearer authentication in http and non-wasm websockets. + [829](https://github.com/gakonst/ethers-rs/pull/829) ### 0.5.3 From a4db7a8ae0df70d11e0f54c57d9a9937f62024b8 Mon Sep 17 00:00:00 2001 From: th4s Date: Tue, 25 Jan 2022 18:48:31 +0100 Subject: [PATCH 06/10] Fixed doc test --- ethers-providers/src/transports/http.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index b8a81e6e8..d7662a1d2 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -112,11 +112,11 @@ impl Provider { /// # Example /// /// ``` - /// use ethers_providers::{Http, Auth}; + /// use ethers_providers::{Authorization, Http}; /// use url::Url; /// /// let url = Url::parse("http://localhost:8545").unwrap(); - /// let provider = Http::new_with_auth(url, Auth::Basic("admin", "good_password")); + /// let provider = Http::new_with_auth(url, Authorization::Basic("admin".into(), "good_password".into())); /// ``` pub fn new_with_auth(url: impl Into, auth: Authorization) -> Self { let mut provider = Self::new(url); From 98d6afb69ca8a4b0665108192a79b8805cfb3f3c Mon Sep 17 00:00:00 2001 From: th4s Date: Wed, 26 Jan 2022 10:49:03 +0100 Subject: [PATCH 07/10] Added constructors for Authorization --- ethers-providers/src/transports/common.rs | 12 +++++++++++- ethers-providers/src/transports/http.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ethers-providers/src/transports/common.rs b/ethers-providers/src/transports/common.rs index fec4be08a..a7ba81d1b 100644 --- a/ethers-providers/src/transports/common.rs +++ b/ethers-providers/src/transports/common.rs @@ -2,7 +2,7 @@ use ethers_core::types::U256; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::fmt; +use std::{fmt, string::ToString}; use thiserror::Error; #[derive(Serialize, Deserialize, Debug, Clone, Error)] @@ -103,6 +103,16 @@ pub enum Authorization { Bearer(String), } +impl Authorization { + pub fn basic(username: impl ToString, password: impl ToString) -> Self { + Self::Basic(username.to_string(), password.to_string()) + } + + pub fn bearer(token: impl ToString) -> Self { + Self::Bearer(token.to_string()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index d7662a1d2..1776ab796 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -116,7 +116,7 @@ impl Provider { /// use url::Url; /// /// let url = Url::parse("http://localhost:8545").unwrap(); - /// let provider = Http::new_with_auth(url, Authorization::Basic("admin".into(), "good_password".into())); + /// let provider = Http::new_with_auth(url, Authorization::basic("admin", "good_password")); /// ``` pub fn new_with_auth(url: impl Into, auth: Authorization) -> Self { let mut provider = Self::new(url); From d8e7956404ba116d124f81b4e428ad4eefd69888 Mon Sep 17 00:00:00 2001 From: th4s Date: Wed, 26 Jan 2022 12:51:33 +0100 Subject: [PATCH 08/10] Improved code quality and implemented feedback --- ethers-providers/src/transports/common.rs | 20 +++++-- ethers-providers/src/transports/http.rs | 69 +++++++++++++++-------- ethers-providers/src/transports/ws.rs | 14 ++--- 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/ethers-providers/src/transports/common.rs b/ethers-providers/src/transports/common.rs index a7ba81d1b..d899a6744 100644 --- a/ethers-providers/src/transports/common.rs +++ b/ethers-providers/src/transports/common.rs @@ -2,7 +2,7 @@ use ethers_core::types::U256; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::{fmt, string::ToString}; +use std::fmt; use thiserror::Error; #[derive(Serialize, Deserialize, Debug, Clone, Error)] @@ -99,17 +99,25 @@ impl ResponseData { /// Use to inject username and password or an auth token into requests #[derive(Clone, Debug)] pub enum Authorization { - Basic(String, String), + Basic(String), Bearer(String), } impl Authorization { - pub fn basic(username: impl ToString, password: impl ToString) -> Self { - Self::Basic(username.to_string(), password.to_string()) + pub fn basic(username: impl Into, password: impl Into) -> Self { + let auth_secret = base64::encode(username.into() + ":" + &password.into()); + Self::Basic(auth_secret) } - pub fn bearer(token: impl ToString) -> Self { - Self::Bearer(token.to_string()) + pub fn bearer(token: impl Into) -> Self { + Self::Bearer(token.into()) + } + + pub(crate) fn into_auth_string(self) -> String { + match self { + Authorization::Basic(auth_secret) => format!("Basic {}", auth_secret), + Authorization::Bearer(token) => format!("Bearer {}", token), + } } } diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index 1776ab796..9b430f43d 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -2,7 +2,7 @@ use crate::{provider::ProviderError, JsonRpcClient}; use async_trait::async_trait; -use reqwest::{Client, Error as ReqwestError}; +use reqwest::{header::HeaderValue, Client, Error as ReqwestError}; use serde::{de::DeserializeOwned, Serialize}; use std::{ str::FromStr, @@ -33,7 +33,6 @@ pub struct Provider { id: AtomicU64, client: Client, url: Url, - authorization: Option, } #[derive(Error, Debug)] @@ -72,17 +71,7 @@ impl JsonRpcClient for Provider { let next_id = self.id.fetch_add(1, Ordering::SeqCst); let payload = Request::new(next_id, method, params); - let mut client = self.client.post(self.url.as_ref()).json(&payload); - if let Some(auth) = &self.authorization { - client = match auth { - Authorization::Basic(username, password) => { - client.basic_auth(username, Some(password)) - } - Authorization::Bearer(token) => client.bearer_auth(token), - }; - } - - let res = client.send().await?; + let res = self.client.post(self.url.as_ref()).json(&payload).send().await?; let text = res.text().await?; let res: Response = serde_json::from_str(&text).map_err(|err| ClientError::SerdeJson { err, text })?; @@ -104,7 +93,7 @@ impl Provider { /// let provider = Http::new(url); /// ``` pub fn new(url: impl Into) -> Self { - Self { id: AtomicU64::new(0), client: Client::new(), url: url.into(), authorization: None } + Self::new_with_client(url, Client::new()) } /// Initializes a new HTTP Client with authentication @@ -118,10 +107,35 @@ impl Provider { /// let url = Url::parse("http://localhost:8545").unwrap(); /// let provider = Http::new_with_auth(url, Authorization::basic("admin", "good_password")); /// ``` - pub fn new_with_auth(url: impl Into, auth: Authorization) -> Self { - let mut provider = Self::new(url); - provider.authorization = Some(auth); - provider + pub fn new_with_auth( + url: impl Into, + auth: Authorization, + ) -> Result { + let mut auth_value = HeaderValue::from_str(&auth.into_auth_string())?; + auth_value.set_sensitive(true); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.insert(reqwest::header::AUTHORIZATION, auth_value); + + let client = Client::builder().default_headers(headers).build()?; + + Ok(Self::new_with_client(url, client)) + } + + /// Allows to customize the provider by providing your own http client + /// + /// # Example + /// + /// ``` + /// use ethers_providers::Http; + /// use url::Url; + /// + /// let url = Url::parse("http://localhost:8545").unwrap(); + /// let client = reqwest::Client::builder().build().unwrap(); + /// let provider = Http::new_with_client(url, client); + /// ``` + pub fn new_with_client(url: impl Into, client: reqwest::Client) -> Self { + Self { id: AtomicU64::new(0), client, url: url.into() } } } @@ -136,11 +150,18 @@ impl FromStr for Provider { impl Clone for Provider { fn clone(&self) -> Self { - Self { - id: AtomicU64::new(0), - client: self.client.clone(), - url: self.url.clone(), - authorization: None, - } + Self { id: AtomicU64::new(0), client: self.client.clone(), url: self.url.clone() } } } + +#[derive(Error, Debug)] +/// Error thrown when dealing with Http clients +pub enum HttpClientError { + /// Thrown if unable to build headers for client + #[error(transparent)] + InvalidHeader(#[from] http::header::InvalidHeaderValue), + + /// Thrown if unable to build client + #[error(transparent)] + ClientBuild(#[from] reqwest::Error), +} diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index 5ee10a23c..587f795bf 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -152,15 +152,11 @@ impl Ws { ) -> Result { let mut request: HttpRequest<()> = HttpRequest::builder().method("GET").uri(Uri::from_str(uri.as_ref())?).body(())?; - let auth_header = match auth { - Authorization::Basic(username, password) => { - String::from("Basic ") + base64::encode(username + ":" + &password).as_str() - } - Authorization::Bearer(token) => String::from("Bearer ") + &token, - }; - request - .headers_mut() - .insert(http::header::AUTHORIZATION, http::HeaderValue::from_str(&auth_header)?); + + let mut auth_value = http::HeaderValue::from_str(&auth.into_auth_string())?; + auth_value.set_sensitive(true); + + request.headers_mut().insert(http::header::AUTHORIZATION, auth_value); Self::connect(request).await } From c6a57d23ead37cfd365ba8d3b76c29ec49026b29 Mon Sep 17 00:00:00 2001 From: th4s Date: Wed, 26 Jan 2022 13:34:39 +0100 Subject: [PATCH 09/10] Made bas64 crate for basic auth encoding non-optional --- ethers-providers/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethers-providers/Cargo.toml b/ethers-providers/Cargo.toml index b4d63e3db..ca494cb2a 100644 --- a/ethers-providers/Cargo.toml +++ b/ethers-providers/Cargo.toml @@ -25,7 +25,7 @@ thiserror = { version = "1.0.30", default-features = false } url = { version = "2.2.2", default-features = false } auto_impl = { version = "0.5.0", default-features = false } http = { version = "0.2", optional = true } -base64 = { version = "0.13", optional = true } +base64 = "0.13" # required for implementing stream on the filters futures-core = { version = "0.3.16", default-features = false } @@ -62,7 +62,7 @@ tempfile = "3.3.0" [features] default = ["ws", "rustls"] celo = ["ethers-core/celo"] -ws = ["tokio", "tokio-tungstenite", "http", "base64"] +ws = ["tokio", "tokio-tungstenite", "http"] ipc = ["tokio", "tokio/io-util", "tokio-util", "bytes"] openssl = ["tokio-tungstenite/native-tls", "reqwest/native-tls"] From ec3378c2aa78aeb8dac2852ccd4a6e8bb861719f Mon Sep 17 00:00:00 2001 From: th4s Date: Wed, 26 Jan 2022 15:28:32 +0100 Subject: [PATCH 10/10] Added `Display` for `Authorization` instead of `into_auth_string` --- ethers-providers/src/transports/common.rs | 8 +++++--- ethers-providers/src/transports/http.rs | 2 +- ethers-providers/src/transports/ws.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ethers-providers/src/transports/common.rs b/ethers-providers/src/transports/common.rs index d899a6744..6162bde62 100644 --- a/ethers-providers/src/transports/common.rs +++ b/ethers-providers/src/transports/common.rs @@ -112,11 +112,13 @@ impl Authorization { pub fn bearer(token: impl Into) -> Self { Self::Bearer(token.into()) } +} - pub(crate) fn into_auth_string(self) -> String { +impl fmt::Display for Authorization { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Authorization::Basic(auth_secret) => format!("Basic {}", auth_secret), - Authorization::Bearer(token) => format!("Bearer {}", token), + Authorization::Basic(auth_secret) => write!(f, "Basic {}", auth_secret), + Authorization::Bearer(token) => write!(f, "Bearer {}", token), } } } diff --git a/ethers-providers/src/transports/http.rs b/ethers-providers/src/transports/http.rs index 9b430f43d..87fc57f9b 100644 --- a/ethers-providers/src/transports/http.rs +++ b/ethers-providers/src/transports/http.rs @@ -111,7 +111,7 @@ impl Provider { url: impl Into, auth: Authorization, ) -> Result { - let mut auth_value = HeaderValue::from_str(&auth.into_auth_string())?; + let mut auth_value = HeaderValue::from_str(&auth.to_string())?; auth_value.set_sensitive(true); let mut headers = reqwest::header::HeaderMap::new(); diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index 587f795bf..fc1ae882c 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -153,7 +153,7 @@ impl Ws { let mut request: HttpRequest<()> = HttpRequest::builder().method("GET").uri(Uri::from_str(uri.as_ref())?).body(())?; - let mut auth_value = http::HeaderValue::from_str(&auth.into_auth_string())?; + let mut auth_value = http::HeaderValue::from_str(&auth.to_string())?; auth_value.set_sensitive(true); request.headers_mut().insert(http::header::AUTHORIZATION, auth_value);