From 25fa9f74b321519088261fd571d5a1fa24e1836b Mon Sep 17 00:00:00 2001 From: durch Date: Mon, 17 Jun 2024 19:28:21 +0200 Subject: [PATCH] Remove tokio and reqwesrt --- Cargo.toml | 15 +++----- src/fetcher.rs | 52 +++++++++++---------------- src/lib.rs | 96 +++++++++----------------------------------------- 3 files changed, 42 insertions(+), 121 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index da223fc63..35b62b139 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "goauth" -version = "0.16.0" +version = "0.17.0-alpha.1" authors = ["Drazen Urch "] description = "Crate for authenticating Server to Server Apps for Google Cloud Engine." repository = "https://github.com/durch/rust-goauth" @@ -16,23 +16,18 @@ path = "src/lib.rs" [dependencies] arc-swap = "1" -serde = "^1" +serde = "1" serde_derive = "1" serde_json = "1" time = "0.3" log = "0.4" -smpl_jwt = {version = "0.8.0", default-features = false} -reqwest = { version = "0.12", features = ["blocking", "json"], default-features = false } -futures = "0.3" +smpl_jwt = { version = "0.8.0", default-features = false } +attohttpc = { version = "0.28", features = ["json", "form"] } simpl = "0.1" -tokio = { version = "1", features = ["rt-multi-thread"] } [dev-dependencies] -tokio = { version = "1", features = ["macros", "rt-multi-thread"] } doc-comment = "0.3" mockito = "0.31" [features] -default = ["reqwest/default-tls"] -vendored-ssl = ["smpl_jwt/vendored", "reqwest/native-tls-vendored"] - +vendored-ssl = ["smpl_jwt/vendored"] diff --git a/src/fetcher.rs b/src/fetcher.rs index 44cfb0660..dedb0e1b1 100644 --- a/src/fetcher.rs +++ b/src/fetcher.rs @@ -6,7 +6,6 @@ use crate::credentials::Credentials; use crate::{get_token_with_client_and_body, Result}; use arc_swap::ArcSwapOption; -use reqwest::Client; use smpl_jwt::Jwt; use std::sync::{Arc, Mutex}; use time::{Duration, OffsetDateTime}; @@ -20,7 +19,6 @@ use time::{Duration, OffsetDateTime}; /// is within the `refresh_buffer` window, it will fetch a new token, store /// that (along with the new expired time), and return the new token. pub struct TokenFetcher { - client: Client, jwt: Arc>>, credentials: Credentials, token_state: ArcSwapOption, @@ -40,16 +38,10 @@ impl TokenFetcher { credentials: Credentials, refresh_buffer_seconds: i64, ) -> TokenFetcher { - TokenFetcher::with_client( - Client::new(), - jwt, - credentials, - Duration::new(refresh_buffer_seconds, 0), - ) + TokenFetcher::with_client(jwt, credentials, Duration::new(refresh_buffer_seconds, 0)) } pub fn with_client( - client: Client, jwt: Jwt, credentials: Credentials, refresh_buffer: Duration, @@ -57,7 +49,6 @@ impl TokenFetcher { let token_state = ArcSwapOption::from(None); TokenFetcher { - client, jwt: Arc::new(Mutex::new(jwt)), credentials, token_state, @@ -69,19 +60,19 @@ impl TokenFetcher { /// currently stored token's `expires_in` field and the configured /// `refresh_buffer`. If it is, return the stored token. If not, /// fetch a new token, store it, and return the new token. - pub async fn fetch_token(&self) -> Result { + pub fn fetch_token(&self) -> Result { let token_state = self.token_state.load(); match &*token_state { // First time calling `fetch_token` since initialization, so fetch // a token. - None => self.get_token().await, + None => self.get_token(), Some(token_state) => { let now = OffsetDateTime::now_utc(); if now >= token_state.refresh_at { // We have an existing token but it is time to refresh it - self.get_token().await + self.get_token() } else { // We have an existing, valid token, so return immediately Ok(token_state.token.clone()) @@ -91,11 +82,10 @@ impl TokenFetcher { } /// Refresh the token - async fn get_token(&self) -> Result { + fn get_token(&self) -> Result { let now = OffsetDateTime::now_utc(); let jwt_body = self.get_jwt_body(now)?; - let token = - get_token_with_client_and_body(&self.client, jwt_body, &self.credentials).await?; + let token = get_token_with_client_and_body(jwt_body, &self.credentials)?; let expires_in = Duration::new(token.expires_in().into(), 0); assert!( @@ -168,8 +158,8 @@ mod tests { (token, json.to_string()) } - #[tokio::test] - async fn basic_token_fetch() { + #[test] + fn basic_token_fetch() { let (jwt, credentials) = get_mocks(); let refresh_buffer = 0; @@ -179,12 +169,12 @@ mod tests { let _mock = mock("POST", "/").with_status(200).with_body(json).create(); - let token = fetcher.fetch_token().await.unwrap(); + let token = fetcher.fetch_token().unwrap(); assert_eq!(expected_token, token); } - #[tokio::test] - async fn basic_token_refresh() { + #[test] + fn basic_token_refresh() { let (jwt, credentials) = get_mocks(); let refresh_buffer = 0; @@ -200,19 +190,19 @@ mod tests { .create(); // this should work - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); // sleep for `expires_in` thread::sleep(StdDuration::from_secs(expires_in.into())); // this should refresh - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); mock.assert(); } - #[tokio::test] - async fn token_refresh_with_buffer() { + #[test] + fn token_refresh_with_buffer() { let (jwt, credentials) = get_mocks(); let refresh_buffer = 4; @@ -228,20 +218,20 @@ mod tests { .create(); // this should work - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); // sleep for `expires_in` let sleep_for = expires_in - (refresh_buffer as u32); thread::sleep(StdDuration::from_secs(sleep_for.into())); // this should refresh - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); mock.assert(); } - #[tokio::test] - async fn doesnt_token_refresh_unnecessarily() { + #[test] + fn doesnt_token_refresh_unnecessarily() { let (jwt, credentials) = get_mocks(); let refresh_buffer = 0; @@ -257,10 +247,10 @@ mod tests { .create(); // this should work - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); // fetch again, should not refresh - fetcher.fetch_token().await.unwrap(); + fetcher.fetch_token().unwrap(); mock.assert(); } diff --git a/src/lib.rs b/src/lib.rs index b8474b105..799470272 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,12 +13,9 @@ pub mod scopes; use auth::{JwtClaims, Token}; use credentials::Credentials; -use reqwest::Client; pub use smpl_jwt::Jwt; use std::str::FromStr; -use tokio::runtime::Runtime; - const DEFAULT_URL: &str = "https://www.googleapis.com/oauth2/v4/token"; fn form_body(body: &str) -> Vec<(&str, &str)> { @@ -33,7 +30,7 @@ simpl::err!(GoErr, Io@std::io::Error; Jwt@smpl_jwt::JwtErr; Json@serde_json::Error; - Reqwest@reqwest::Error; + Reqwest@attohttpc::Error; Token@auth::TokenErr; }); @@ -74,12 +71,10 @@ simpl::err!(GoErr, /// ``` #[allow(clippy::result_large_err)] pub fn get_token_legacy(jwt: &Jwt, url: Option<&str>) -> Result { - let client = reqwest::blocking::Client::new(); let final_jwt = jwt.finalize()?; let request_body = form_body(&final_jwt); - let response = client - .post(url.unwrap_or(DEFAULT_URL)) - .form(&request_body) + let response = attohttpc::post(url.unwrap_or(DEFAULT_URL)) + .form(&request_body)? .send()?; Token::from_str(&response.text()?) @@ -90,61 +85,14 @@ pub fn get_token_as_string_legacy(jwt: &Jwt, url: Option<&str>) -> Re Ok(serde_json::to_string(&get_token_legacy(jwt, url)?)?) } -#[allow(clippy::result_large_err)] -pub fn get_token_as_string(jwt: &Jwt, credentials: &Credentials) -> Result { - Ok(serde_json::to_string(&get_token_blocking( - jwt, - credentials, - )?)?) -} - -/// Get Token which can be used to authenticate further request -/// ### Example -/// -/// ``` -/// extern crate smpl_jwt; -/// extern crate goauth; -/// #[macro_use] -/// extern crate log; -/// -/// use goauth::auth::JwtClaims; -/// use goauth::scopes::Scope; -/// use goauth::credentials::Credentials; -/// use goauth::get_token_blocking; -/// use smpl_jwt::Jwt; -/// -/// fn main() { -/// -/// let credentials = Credentials::from_file("dummy_credentials_file_for_tests.json").unwrap(); -/// -/// let claims = JwtClaims::new(credentials.iss(), -/// &[Scope::DevStorageReadWrite], -/// credentials.token_uri(), -/// None, None); -/// -/// let jwt = Jwt::new(claims, credentials.rsa_key().unwrap(), None); -/// match get_token_blocking(&jwt, &credentials) { -/// Ok(x) => debug!("{}", x), -/// Err(e) => debug!("{}", e) -/// }; -/// } -/// -/// ``` -#[allow(clippy::result_large_err)] -pub fn get_token_blocking(jwt: &Jwt, credentials: &Credentials) -> Result { - let rt = Runtime::new()?; - rt.block_on(get_token(jwt, credentials)) -} - /// Async get Token which can be used to authenticate further request /// ### Example /// -/// ``` +/// ```rust no_run /// extern crate smpl_jwt; /// extern crate goauth; /// #[macro_use] /// extern crate log; -/// extern crate futures; /// /// use goauth::auth::JwtClaims; /// use goauth::scopes::Scope; @@ -152,7 +100,6 @@ pub fn get_token_blocking(jwt: &Jwt, credentials: &Credentials) -> Re /// use goauth::GoErr; /// use goauth::get_token; /// use smpl_jwt::Jwt; -/// use futures::future::Future; /// /// /// fn main() -> Result<(), GoErr> { @@ -165,50 +112,39 @@ pub fn get_token_blocking(jwt: &Jwt, credentials: &Credentials) -> Re /// None, None); /// /// let jwt = Jwt::new(claims, credentials.rsa_key().unwrap(), None); -/// async { -/// match get_token(&jwt, &credentials).await { +/// match get_token(&jwt, &credentials) { /// Ok(token) => println!("{}", token), -/// Err(_) => panic!("An error occurred, somewhere in there, try debugging with `get_token_with_creds`") -/// } +/// Err(e) => panic!("{}", e) /// }; /// Ok(()) /// } /// /// ``` -pub async fn get_token(jwt: &Jwt, credentials: &Credentials) -> Result { - let client = Client::new(); - - get_token_with_client(&client, jwt, credentials).await +pub fn get_token(jwt: &Jwt, credentials: &Credentials) -> Result { + get_token_with_client(jwt, credentials) } -pub async fn get_token_with_client( - client: &Client, - jwt: &Jwt, - credentials: &Credentials, -) -> Result { +pub fn get_token_with_client(jwt: &Jwt, credentials: &Credentials) -> Result { let jwt_body = jwt.finalize()?; - get_token_with_client_and_body(client, jwt_body, credentials).await + get_token_with_client_and_body(jwt_body, credentials) } -pub(crate) async fn get_token_with_client_and_body( - client: &Client, +pub(crate) fn get_token_with_client_and_body( jwt_body: String, credentials: &Credentials, ) -> Result { let request_body = form_body(&jwt_body); - let response = client - .post(&credentials.token_uri()) - .form(&request_body) - .send() - .await?; + let response = attohttpc::post(credentials.token_uri()) + .form(&request_body)? + .send()?; if response.status().is_success() { - let token = response.json::().await?; + let token = response.json::()?; Ok(token) } else { - let token_err = response.json::().await?; + let token_err = response.json::()?; Err(GoErr::from(token_err)) } }