From a38b6aa1edad3cda6970a064d36779aba2f1f2f7 Mon Sep 17 00:00:00 2001 From: asonix Date: Mon, 30 Mar 2020 00:53:45 -0500 Subject: [PATCH] Don't use async-trait --- http-signature-normalization-actix/Cargo.toml | 1 - .../examples/client.rs | 21 ++++-- .../examples/server.rs | 6 +- .../src/digest/mod.rs | 31 ++++----- .../src/digest/sign.rs | 68 ++++++++++++------- http-signature-normalization-actix/src/lib.rs | 43 ++++++++---- .../src/sign.rs | 36 ++++++---- 7 files changed, 132 insertions(+), 74 deletions(-) diff --git a/http-signature-normalization-actix/Cargo.toml b/http-signature-normalization-actix/Cargo.toml index 03655eb..60649c8 100644 --- a/http-signature-normalization-actix/Cargo.toml +++ b/http-signature-normalization-actix/Cargo.toml @@ -27,7 +27,6 @@ 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/examples/client.rs b/http-signature-normalization-actix/examples/client.rs index 537d28b..83782ca 100644 --- a/http-signature-normalization-actix/examples/client.rs +++ b/http-signature-normalization-actix/examples/client.rs @@ -1,19 +1,20 @@ -use actix_web::client::Client; +use actix_web::{client::Client, error::BlockingError}; use http_signature_normalization_actix::prelude::*; use sha2::{Digest, Sha256}; use std::time::SystemTime; async fn request(config: Config) -> Result<(), Box> { - let mut digest = Sha256::new(); + let digest = Sha256::new(); let mut response = Client::default() .post("http://127.0.0.1:8010/") .header("User-Agent", "Actix Web") .set(actix_web::http::header::Date(SystemTime::now().into())) - .signature_with_digest(&config, "my-key-id", &mut digest, "Hewwo-owo", |s| { + .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { println!("Signing String\n{}", s); Ok(base64::encode(s)) as Result<_, MyError> - })? + }) + .await? .send() .await .map_err(|e| { @@ -55,4 +56,16 @@ pub enum MyError { #[error("Failed to retrieve request body")] Body, + + #[error("Blocking operation was canceled")] + Canceled, +} + +impl From> for MyError { + fn from(b: BlockingError) -> Self { + match b { + BlockingError::Error(e) => e, + _ => MyError::Canceled, + } + } } diff --git a/http-signature-normalization-actix/examples/server.rs b/http-signature-normalization-actix/examples/server.rs index 75204ae..1b8bd8b 100644 --- a/http-signature-normalization-actix/examples/server.rs +++ b/http-signature-normalization-actix/examples/server.rs @@ -1,4 +1,7 @@ -use actix_web::{http::StatusCode, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError}; +use actix_web::{ + http::StatusCode, middleware::Logger, web, App, HttpRequest, HttpResponse, HttpServer, + ResponseError, +}; use futures::future::{err, ok, Ready}; use http_signature_normalization_actix::prelude::*; use log::info; @@ -59,6 +62,7 @@ async fn main() -> Result<(), Box> { App::new() .wrap(VerifyDigest::new(Sha256::new()).optional()) .wrap(VerifySignature::new(MyVerify, config.clone()).optional()) + .wrap(Logger::default()) .route("/", web::post().to(index)) }) .bind("127.0.0.1:8010")? diff --git a/http-signature-normalization-actix/src/digest/mod.rs b/http-signature-normalization-actix/src/digest/mod.rs index f8ad6b2..ed8fcd9 100644 --- a/http-signature-normalization-actix/src/digest/mod.rs +++ b/http-signature-normalization-actix/src/digest/mod.rs @@ -10,7 +10,7 @@ use actix_web::{ error::BlockingError, http::header::{InvalidHeaderValue, ToStrError}, }; -use std::{fmt::Display, future::Future}; +use std::{fmt::Display, future::Future, pin::Pin}; use crate::{Config, Sign}; @@ -44,17 +44,16 @@ 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 - async fn authorization_signature_with_digest( + fn authorization_signature_with_digest( self, - config: &Config, + config: Config, key_id: K, - digest: &mut D, + digest: D, v: V, f: F, - ) -> Result, E> + ) -> Pin, E>>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -63,20 +62,20 @@ pub trait SignExt: Sign { + std::fmt::Debug + Send + 'static, - K: Display, - D: DigestCreate, - V: AsRef<[u8]>, + K: Display + 'static, + D: DigestCreate + Send + 'static, + V: AsRef<[u8]> + Send + 'static, Self: Sized; /// Set the Digest and Signature headers on the request - async fn signature_with_digest( + fn signature_with_digest( self, - config: &Config, + config: Config, key_id: K, - digest: &mut D, + digest: D, v: V, f: F, - ) -> Result, E> + ) -> Pin, E>>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -85,9 +84,9 @@ pub trait SignExt: Sign { + std::fmt::Debug + Send + 'static, - K: Display, - D: DigestCreate, - V: AsRef<[u8]>, + K: Display + 'static, + D: DigestCreate + Send + 'static, + V: AsRef<[u8]> + Send + 'static, Self: Sized; } diff --git a/http-signature-normalization-actix/src/digest/sign.rs b/http-signature-normalization-actix/src/digest/sign.rs index 0d28b97..f8e1063 100644 --- a/http-signature-normalization-actix/src/digest/sign.rs +++ b/http-signature-normalization-actix/src/digest/sign.rs @@ -2,24 +2,24 @@ use actix_web::{ client::ClientRequest, error::BlockingError, http::header::{InvalidHeaderValue, ToStrError}, + web, }; -use std::fmt::Display; +use std::{fmt::Display, future::Future, pin::Pin}; use crate::{ digest::{DigestClient, DigestCreate, SignExt}, Config, Sign, }; -#[async_trait::async_trait(?Send)] impl SignExt for ClientRequest { - async fn authorization_signature_with_digest( + fn authorization_signature_with_digest( self, - config: &Config, + config: Config, key_id: K, - digest: &mut D, + mut digest: D, v: V, f: F, - ) -> Result, E> + ) -> Pin, E>>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -28,27 +28,35 @@ impl SignExt for ClientRequest { + std::fmt::Debug + Send + 'static, - K: Display, - D: DigestCreate, - V: AsRef<[u8]>, + K: Display + 'static, + D: DigestCreate + Send + 'static, + V: AsRef<[u8]> + Send + 'static, Self: Sized, { - let digest = digest.compute(v.as_ref()); + Box::pin(async move { + let (d, v) = web::block(move || { + let d = digest.compute(v.as_ref()); + Ok((d, v)) as Result<(String, V), E> + }) + .await?; - self.set_header("Digest", format!("{}={}", D::NAME, digest)) - .authorization_signature(config, key_id, f) - .await - .map(|c| DigestClient::new(c, v)) + let c = self + .set_header("Digest", format!("{}={}", D::NAME, d)) + .authorization_signature(config, key_id, f) + .await?; + + Ok(DigestClient::new(c, v)) + }) } - async fn signature_with_digest( + fn signature_with_digest( self, - config: &Config, + config: Config, key_id: K, - digest: &mut D, + mut digest: D, v: V, f: F, - ) -> Result, E> + ) -> Pin, E>>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -57,16 +65,24 @@ impl SignExt for ClientRequest { + std::fmt::Debug + Send + 'static, - K: Display, - D: DigestCreate, - V: AsRef<[u8]>, + K: Display + 'static, + D: DigestCreate + Send + 'static, + V: AsRef<[u8]> + Send + 'static, Self: Sized, { - let digest = digest.compute(v.as_ref()); + Box::pin(async move { + let (d, v) = web::block(move || { + let d = digest.compute(v.as_ref()); + Ok((d, v)) as Result<(String, V), E> + }) + .await?; - self.set_header("Digest", format!("{}={}", D::NAME, digest)) - .signature(config, key_id, f) - .await - .map(|c| DigestClient::new(c, v)) + let c = self + .set_header("Digest", format!("{}={}", D::NAME, d)) + .signature(config, key_id, f) + .await?; + + Ok(DigestClient::new(c, v)) + }) } } diff --git a/http-signature-normalization-actix/src/lib.rs b/http-signature-normalization-actix/src/lib.rs index bea96fd..f319811 100644 --- a/http-signature-normalization-actix/src/lib.rs +++ b/http-signature-normalization-actix/src/lib.rs @@ -99,21 +99,24 @@ //! //! ### Use it in a client //! ```rust,ignore -//! use actix_web::client::Client; +//! use actix_web::{client::Client, error::BlockingError}; //! use http_signature_normalization_actix::prelude::*; //! use sha2::{Digest, Sha256}; //! //! #[actix_rt::main] //! async fn main() -> Result<(), Box> { //! let config = Config::default(); -//! let mut digest = Sha256::new(); +//! let digest = Sha256::new(); //! //! let mut response = Client::default() //! .post("http://127.0.0.1:8010/") //! .header("User-Agent", "Actix Web") -//! .authorization_signature_with_digest(&config, "my-key-id", &mut digest, "Hewwo-owo", |s| { +//! .set(actix_web::http::header::Date(SystemTime::now().into())) +//! .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { +//! println!("Signing String\n{}", s); //! Ok(base64::encode(s)) as Result<_, MyError> -//! })? +//! }) +//! .await? //! .send() //! .await //! .map_err(|e| { @@ -143,6 +146,18 @@ //! //! #[error("Failed to retrieve request body")] //! Body, +//! +//! #[error("Blocking operation was canceled")] +//! Canceled, +//! } +//! +//! impl From> for MyError { +//! fn from(b: BlockingError) -> Self { +//! match b { +//! BlockingError::Error(e) => e, +//! _ => MyError::Canceled, +//! } +//! } //! } //! ``` @@ -155,7 +170,7 @@ use actix_web::{ }, }; use chrono::Duration; -use std::{collections::BTreeMap, fmt::Display, future::Future}; +use std::{collections::BTreeMap, fmt::Display, future::Future, pin::Pin}; mod sign; @@ -216,15 +231,14 @@ 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 - async fn authorization_signature( + fn authorization_signature( self, - config: &Config, + config: Config, key_id: K, f: F, - ) -> Result + ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -233,11 +247,16 @@ pub trait Sign { + std::fmt::Debug + Send + 'static, - K: Display, + K: Display + 'static, Self: Sized; /// Add a Signature to the request - async fn signature(self, config: &Config, key_id: K, f: F) -> Result + fn signature( + self, + config: Config, + key_id: K, + f: F, + ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -246,7 +265,7 @@ pub trait Sign { + std::fmt::Debug + Send + 'static, - K: Display, + K: Display + 'static, Self: Sized; } diff --git a/http-signature-normalization-actix/src/sign.rs b/http-signature-normalization-actix/src/sign.rs index 204abd8..131b4f9 100644 --- a/http-signature-normalization-actix/src/sign.rs +++ b/http-signature-normalization-actix/src/sign.rs @@ -4,18 +4,17 @@ use actix_web::{ http::header::{InvalidHeaderValue, ToStrError}, web, }; -use std::fmt::Display; +use std::{fmt::Display, future::Future, pin::Pin}; use crate::{create::Signed, Config, Sign}; -#[async_trait::async_trait(?Send)] impl Sign for ClientRequest { - async fn authorization_signature( + fn authorization_signature( mut self, - config: &Config, + config: Config, key_id: K, f: F, - ) -> Result + ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -24,15 +23,22 @@ impl Sign for ClientRequest { + std::fmt::Debug + Send + 'static, - K: Display, + K: Display + 'static, Self: Sized, { - let signed = prepare(&self, config, key_id, f).await?; - signed.authorization_header(self.headers_mut())?; - Ok(self) + Box::pin(async move { + let signed = prepare(&self, &config, key_id, f).await?; + signed.authorization_header(self.headers_mut())?; + Ok(self) + }) } - async fn signature(mut self, config: &Config, key_id: K, f: F) -> Result + fn signature( + mut self, + config: Config, + key_id: K, + f: F, + ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From> @@ -41,12 +47,14 @@ impl Sign for ClientRequest { + std::fmt::Debug + Send + 'static, - K: Display, + K: Display + 'static, Self: Sized, { - let signed = prepare(&self, config, key_id, f).await?; - signed.signature_header(self.headers_mut())?; - Ok(self) + Box::pin(async move { + let signed = prepare(&self, &config, key_id, f).await?; + signed.signature_header(self.headers_mut())?; + Ok(self) + }) } }