diff --git a/http-signature-normalization-actix/Cargo.toml b/http-signature-normalization-actix/Cargo.toml index 60649c8..03655eb 100644 --- a/http-signature-normalization-actix/Cargo.toml +++ b/http-signature-normalization-actix/Cargo.toml @@ -27,6 +27,7 @@ required-features = ["sha-2"] [dependencies] actix-web = "3.0.0-alpha.1" actix-http = "2.0.0-alpha.2" +async-trait = "0.1.27" base64 = { version = "0.11", optional = true } bytes = "0.5.4" chrono = "0.4.6" diff --git a/http-signature-normalization-actix/src/digest/mod.rs b/http-signature-normalization-actix/src/digest/mod.rs index 0472193..f8ad6b2 100644 --- a/http-signature-normalization-actix/src/digest/mod.rs +++ b/http-signature-normalization-actix/src/digest/mod.rs @@ -7,6 +7,7 @@ use actix_http::encoding::Decoder; use actix_web::{ client::{ClientRequest, ClientResponse, SendRequestError}, dev::Payload, + error::BlockingError, http::header::{InvalidHeaderValue, ToStrError}, }; use std::{fmt::Display, future::Future}; @@ -43,9 +44,10 @@ pub trait DigestVerify { /// It generates HTTP Signatures after the Digest header has been added, in order to have /// verification that the body has not been tampered with, or that the request can't be replayed by /// a malicious entity +#[async_trait::async_trait(?Send)] pub trait SignExt: Sign { /// Set the Digest and Authorization headers on the request - fn authorization_signature_with_digest( + async fn authorization_signature_with_digest( self, config: &Config, key_id: K, @@ -54,15 +56,20 @@ pub trait SignExt: Sign { f: F, ) -> Result, E> where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, D: DigestCreate, V: AsRef<[u8]>, Self: Sized; /// Set the Digest and Signature headers on the request - fn signature_with_digest( + async fn signature_with_digest( self, config: &Config, key_id: K, @@ -71,8 +78,13 @@ pub trait SignExt: Sign { f: F, ) -> Result, E> where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, D: DigestCreate, V: AsRef<[u8]>, diff --git a/http-signature-normalization-actix/src/digest/sign.rs b/http-signature-normalization-actix/src/digest/sign.rs index 267849c..0d28b97 100644 --- a/http-signature-normalization-actix/src/digest/sign.rs +++ b/http-signature-normalization-actix/src/digest/sign.rs @@ -1,5 +1,6 @@ use actix_web::{ client::ClientRequest, + error::BlockingError, http::header::{InvalidHeaderValue, ToStrError}, }; use std::fmt::Display; @@ -9,8 +10,9 @@ use crate::{ Config, Sign, }; +#[async_trait::async_trait(?Send)] impl SignExt for ClientRequest { - fn authorization_signature_with_digest( + async fn authorization_signature_with_digest( self, config: &Config, key_id: K, @@ -19,8 +21,13 @@ impl SignExt for ClientRequest { f: F, ) -> Result, E> where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, D: DigestCreate, V: AsRef<[u8]>, @@ -30,10 +37,11 @@ impl SignExt for ClientRequest { self.set_header("Digest", format!("{}={}", D::NAME, digest)) .authorization_signature(config, key_id, f) + .await .map(|c| DigestClient::new(c, v)) } - fn signature_with_digest( + async fn signature_with_digest( self, config: &Config, key_id: K, @@ -42,8 +50,13 @@ impl SignExt for ClientRequest { f: F, ) -> Result, E> where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, D: DigestCreate, V: AsRef<[u8]>, @@ -53,6 +66,7 @@ impl SignExt for ClientRequest { self.set_header("Digest", format!("{}={}", D::NAME, digest)) .signature(config, key_id, f) + .await .map(|c| DigestClient::new(c, v)) } } diff --git a/http-signature-normalization-actix/src/lib.rs b/http-signature-normalization-actix/src/lib.rs index 28208b0..bea96fd 100644 --- a/http-signature-normalization-actix/src/lib.rs +++ b/http-signature-normalization-actix/src/lib.rs @@ -146,10 +146,13 @@ //! } //! ``` -use actix_web::http::{ - header::{HeaderMap, InvalidHeaderValue, ToStrError}, - uri::PathAndQuery, - Method, +use actix_web::{ + error::BlockingError, + http::{ + header::{HeaderMap, InvalidHeaderValue, ToStrError}, + uri::PathAndQuery, + Method, + }, }; use chrono::Duration; use std::{collections::BTreeMap, fmt::Display, future::Future}; @@ -213,20 +216,36 @@ pub trait SignatureVerify { } /// A trait implemented by the Actix Web ClientRequest type to add an HTTP signature to the request +#[async_trait::async_trait(?Send)] pub trait Sign { /// Add an Authorization Signature to the request - fn authorization_signature(self, config: &Config, key_id: K, f: F) -> Result + async fn authorization_signature( + self, + config: &Config, + key_id: K, + f: F, + ) -> Result where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, Self: Sized; /// Add a Signature to the request - fn signature(self, config: &Config, key_id: K, f: F) -> Result + async fn signature(self, config: &Config, key_id: K, f: F) -> Result where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, Self: Sized; } diff --git a/http-signature-normalization-actix/src/sign.rs b/http-signature-normalization-actix/src/sign.rs index 27d1157..204abd8 100644 --- a/http-signature-normalization-actix/src/sign.rs +++ b/http-signature-normalization-actix/src/sign.rs @@ -1,44 +1,64 @@ use actix_web::{ client::ClientRequest, + error::BlockingError, http::header::{InvalidHeaderValue, ToStrError}, + web, }; use std::fmt::Display; use crate::{create::Signed, Config, Sign}; +#[async_trait::async_trait(?Send)] impl Sign for ClientRequest { - fn authorization_signature( + async fn authorization_signature( mut self, config: &Config, key_id: K, f: F, ) -> Result where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, + Self: Sized, { - let signed = prepare(&self, config, key_id, f)?; + let signed = prepare(&self, config, key_id, f).await?; signed.authorization_header(self.headers_mut())?; Ok(self) } - fn signature(mut self, config: &Config, key_id: K, f: F) -> Result + async fn signature(mut self, config: &Config, key_id: K, f: F) -> Result where - F: FnOnce(&str) -> Result, - E: From + From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + + From + + From + + std::fmt::Debug + + Send + + 'static, K: Display, + Self: Sized, { - let signed = prepare(&self, config, key_id, f)?; + let signed = prepare(&self, config, key_id, f).await?; signed.signature_header(self.headers_mut())?; Ok(self) } } -fn prepare(request: &ClientRequest, config: &Config, key_id: K, f: F) -> Result +async fn prepare( + request: &ClientRequest, + config: &Config, + key_id: K, + f: F, +) -> Result where - F: FnOnce(&str) -> Result, - E: From, + F: FnOnce(&str) -> Result + Send + 'static, + E: From> + From + std::fmt::Debug + Send + 'static, K: Display, { let unsigned = config.begin_sign( @@ -49,7 +69,7 @@ where let key_id = key_id.to_string(); - let signed = unsigned.sign(key_id, f)?; + let signed = web::block(move || unsigned.sign(key_id, f)).await?; Ok(signed) }