From f079464cef7e7b17f6b19fa74a894554c0f2671c Mon Sep 17 00:00:00 2001 From: hewigovens <360470+hewigovens@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:14:31 +0900 Subject: [PATCH] Add basic auth support --- Cargo.lock | 5 ++- Cargo.toml | 4 +- README.md | 4 +- examples/ethereum-rpc/Cargo.toml | 2 +- examples/ethereum-rpc/src/ethereum_rpc.rs | 10 +++-- reqwest-enum/Cargo.toml | 3 ++ reqwest-enum/src/http.rs | 7 ++++ reqwest-enum/src/jsonrpc.rs | 8 +--- reqwest-enum/src/provider.rs | 47 ++++++++++++++++++++--- reqwest-enum/src/target.rs | 9 ++++- 10 files changed, 76 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d40be5..0b27b8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,7 +145,7 @@ dependencies = [ [[package]] name = "ethereum-rpc" -version = "0.1.1" +version = "0.2.0" dependencies = [ "reqwest", "reqwest-enum", @@ -745,12 +745,13 @@ dependencies = [ [[package]] name = "reqwest-enum" -version = "0.1.1" +version = "0.2.0" dependencies = [ "futures", "reqwest", "serde", "serde_json", + "tokio-test", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 66b8928..aa0e44d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -package.version = "0.1.1" +package.version = "0.2.0" package.edition = "2021" package.documentation = "https://docs.rs/reqwest_enum" package.authors = ["Tao Xu "] @@ -16,5 +16,5 @@ reqwest = { version = "^0.12.0", features = ["json"] } serde = { version = "^1.0.0", features = ["derive"] } serde_json = "^1.0.0" -async-trait = "^0.1.0" futures = "^0.3.0" +tokio-test = "0.4.2" diff --git a/README.md b/README.md index b9f8f9b..936c9de 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Features: ```toml [dependencies] -reqwest-enum = "0.1.0" +reqwest-enum = "0.2.0" ``` ## Example @@ -30,6 +30,7 @@ reqwest-enum = "0.1.0" pub enum HttpBin { Get, Post, + Bearer, } ``` @@ -42,6 +43,7 @@ pub trait Target { fn path(&self) -> &'static str; fn query(&self) -> HashMap<&'static str, &'static str>; fn headers(&self) -> HashMap<&'static str, &'static str>; + fn authentication(&self) -> Option; fn body(&self) -> HTTPBody; } ``` diff --git a/examples/ethereum-rpc/Cargo.toml b/examples/ethereum-rpc/Cargo.toml index 6182a36..db87010 100644 --- a/examples/ethereum-rpc/Cargo.toml +++ b/examples/ethereum-rpc/Cargo.toml @@ -11,4 +11,4 @@ reqwest = { workspace = true } reqwest-enum = { workspace = true, features = ["jsonrpc"] } [dev-dependencies] -tokio-test = "0.4.2" +tokio-test = { workspace = true } diff --git a/examples/ethereum-rpc/src/ethereum_rpc.rs b/examples/ethereum-rpc/src/ethereum_rpc.rs index b9a181f..08a63b9 100644 --- a/examples/ethereum-rpc/src/ethereum_rpc.rs +++ b/examples/ethereum-rpc/src/ethereum_rpc.rs @@ -1,9 +1,9 @@ extern crate reqwest; extern crate reqwest_enum; -use reqwest_enum::jsonrpc::{JsonRpcRequest, JsonRpcTarget}; +use reqwest_enum::jsonrpc::JsonRpcRequest; use reqwest_enum::{ - http::{HTTPBody, HTTPMethod}, - target::Target, + http::{AuthMethod, HTTPBody, HTTPMethod}, + target::{JsonRpcTarget, Target}, }; use serde::{Deserialize, Serialize}; use serde_json::{Number, Value}; @@ -158,6 +158,10 @@ impl Target for EthereumRPC { headers } + fn authentication(&self) -> Option { + None + } + fn body(&self) -> HTTPBody { let method = self.method_name(); let params = self.params(); diff --git a/reqwest-enum/Cargo.toml b/reqwest-enum/Cargo.toml index 5a4952f..2f2ea22 100644 --- a/reqwest-enum/Cargo.toml +++ b/reqwest-enum/Cargo.toml @@ -20,3 +20,6 @@ reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } futures = { workspace = true, optional = true } + +[dev-dependencies] +tokio-test = { workspace = true } diff --git a/reqwest-enum/src/http.rs b/reqwest-enum/src/http.rs index 7a38978..4ca8ed0 100644 --- a/reqwest-enum/src/http.rs +++ b/reqwest-enum/src/http.rs @@ -56,3 +56,10 @@ impl HTTPBody { } } } + +pub enum AuthMethod { + // Basic(username, password) + Basic(&'static str, &'static str), + // Bearer(token) + Bearer(&'static str), +} diff --git a/reqwest-enum/src/jsonrpc.rs b/reqwest-enum/src/jsonrpc.rs index 5f5ad39..cd26c6f 100644 --- a/reqwest-enum/src/jsonrpc.rs +++ b/reqwest-enum/src/jsonrpc.rs @@ -1,4 +1,4 @@ -use crate::{http::HTTPBody, target::Target}; +use crate::http::HTTPBody; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -88,12 +88,6 @@ pub enum JsonRpcResult { Error(JsonRpcErrorResponse), } -#[cfg(feature = "jsonrpc")] -pub trait JsonRpcTarget: Target { - fn method_name(&self) -> &'static str; - fn params(&self) -> Vec; -} - #[cfg(feature = "jsonrpc")] #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] diff --git a/reqwest-enum/src/provider.rs b/reqwest-enum/src/provider.rs index e7acc5c..f419a78 100644 --- a/reqwest-enum/src/provider.rs +++ b/reqwest-enum/src/provider.rs @@ -1,10 +1,12 @@ #[cfg(feature = "jsonrpc")] -use crate::jsonrpc::{JsonRpcError, JsonRpcRequest, JsonRpcResult, JsonRpcTarget}; +use crate::jsonrpc::{JsonRpcError, JsonRpcRequest, JsonRpcResult}; +#[cfg(feature = "jsonrpc")] +use crate::target::JsonRpcTarget; #[cfg(feature = "jsonrpc")] use futures::future::join_all; use crate::{ - http::{HTTPBody, HTTPResponse}, + http::{AuthMethod, HTTPBody, HTTPResponse}, target::Target, }; use core::future::Future; @@ -189,6 +191,16 @@ where request = request.header(k, v); } } + if let Some(auth) = target.authentication() { + match auth { + AuthMethod::Basic(username, password) => { + request = request.basic_auth(username, Some(password)); + } + AuthMethod::Bearer(token) => { + request = request.bearer_auth(token); + } + } + } request } } @@ -208,13 +220,13 @@ where #[cfg(test)] mod tests { use crate::{ - http::{HTTPBody, HTTPMethod}, - provider::Provider, + http::{AuthMethod, HTTPBody, HTTPMethod}, + provider::{JsonProviderType, Provider}, target::Target, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; - + use tokio_test::block_on; #[derive(Serialize, Deserialize)] struct Person { name: String, @@ -225,6 +237,7 @@ mod tests { enum HttpBin { Get, Post, + Bearer, } impl Target for HttpBin { @@ -236,6 +249,7 @@ mod tests { match self { HttpBin::Get => HTTPMethod::GET, HttpBin::Post => HTTPMethod::POST, + HttpBin::Bearer => HTTPMethod::GET, } } @@ -243,6 +257,7 @@ mod tests { match self { HttpBin::Get => "/get", HttpBin::Post => "/post", + HttpBin::Bearer => "/bearer", } } @@ -254,9 +269,16 @@ mod tests { HashMap::default() } + fn authentication(&self) -> Option { + match self { + HttpBin::Bearer => Some(AuthMethod::Bearer("token")), + _ => None, + } + } + fn body(&self) -> HTTPBody { match self { - HttpBin::Get => HTTPBody::default(), + HttpBin::Get | HttpBin::Bearer => HTTPBody::default(), HttpBin::Post => HTTPBody::from(&Person { name: "test".to_string(), age: 20, @@ -277,4 +299,17 @@ mod tests { let provider = Provider::::new(|_: &HttpBin| "http://httpbin.org".to_string()); assert_eq!(provider.request_url(&HttpBin::Post), "http://httpbin.org"); } + + #[test] + fn test_authentication() { + let provider = Provider::::default(); + block_on(async { + let response: serde_json::Value = provider + .request_json(HttpBin::Bearer) + .await + .expect("request error"); + + assert!(response["authenticated"].as_bool().unwrap()); + }); + } } diff --git a/reqwest-enum/src/target.rs b/reqwest-enum/src/target.rs index e535b8e..7ed7113 100644 --- a/reqwest-enum/src/target.rs +++ b/reqwest-enum/src/target.rs @@ -1,4 +1,4 @@ -use crate::http::{HTTPBody, HTTPMethod}; +use crate::http::{AuthMethod, HTTPBody, HTTPMethod}; use std::collections::HashMap; pub trait Target { fn base_url(&self) -> &'static str; @@ -6,5 +6,12 @@ pub trait Target { fn path(&self) -> &'static str; fn query(&self) -> HashMap<&'static str, &'static str>; fn headers(&self) -> HashMap<&'static str, &'static str>; + fn authentication(&self) -> Option; fn body(&self) -> HTTPBody; } + +#[cfg(feature = "jsonrpc")] +pub trait JsonRpcTarget: Target { + fn method_name(&self) -> &'static str; + fn params(&self) -> Vec; +}