Update to actix-web 4.0 beta.1

This commit is contained in:
asonix 2021-02-03 19:02:19 -06:00
parent 894001efe6
commit d04612a729
4 changed files with 33 additions and 47 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "http-signature-normalization-actix" name = "http-signature-normalization-actix"
description = "An HTTP Signatures library that leaves the signing to you" description = "An HTTP Signatures library that leaves the signing to you"
version = "0.4.1" version = "0.5.0-beta.1"
authors = ["asonix <asonix@asonix.dog>"] authors = ["asonix <asonix@asonix.dog>"]
license-file = "LICENSE" license-file = "LICENSE"
readme = "README.md" readme = "README.md"
@ -25,8 +25,8 @@ name = "client"
required-features = ["sha-2"] required-features = ["sha-2"]
[dependencies] [dependencies]
actix-web = { version = "3.0.1", default-features = false } actix-web = { version = "4.0.0-beta.1", default-features = false }
awc = { version = "2.0.0", default-features = false } awc = { version = "3.0.0-beta.1", default-features = false }
base64 = { version = "0.12", optional = true } base64 = { version = "0.12", optional = true }
bytes = "0.5.4" bytes = "0.5.4"
chrono = "0.4.6" chrono = "0.4.6"
@ -38,5 +38,5 @@ sha3 = { version = "0.9", optional = true }
thiserror = "1.0" thiserror = "1.0"
[dev-dependencies] [dev-dependencies]
actix-rt = "1.1.1" actix-rt = "=2.0.0-beta.1"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"

View file

@ -13,10 +13,10 @@ This crate provides extensions the ClientRequest type from Actix Web, and provid
#### First, add this crate to your dependencies #### First, add this crate to your dependencies
```toml ```toml
actix-rt = "1.1.1" actix-rt = "=2.0.0-beta.1"
actix-web = "3.0.2" actix-web = "4.0.0-beta.1"
thiserror = "0.1" thiserror = "0.1"
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] } http-signature-normalization-actix = { version = "0.5.0-beta.1", default-features = false, features = ["sha-2"] }
sha2 = "0.9" sha2 = "0.9"
``` ```

View file

@ -7,15 +7,10 @@ use actix_web::{
http::{header::HeaderValue, StatusCode}, http::{header::HeaderValue, StatusCode},
web, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError, web, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
}; };
use bytes::Bytes; use futures::{channel::mpsc, Stream, StreamExt};
use futures::{
channel::mpsc,
future::{err, ok, ready, Ready},
Stream, StreamExt,
};
use log::{debug, warn}; use log::{debug, warn};
use std::{ use std::{
future::Future, future::{ready, Future, Ready},
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
@ -85,15 +80,13 @@ impl FromRequest for DigestVerified {
} }
} }
impl<T, S, B> Transform<S> for VerifyDigest<T> impl<T, S, B> Transform<S, ServiceRequest> for VerifyDigest<T>
where where
T: DigestVerify + Clone + Send + 'static, T: DigestVerify + Clone + Send + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
+ 'static,
S::Error: 'static, S::Error: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = actix_web::Error; type Error = actix_web::Error;
type Transform = VerifyMiddleware<T, S>; type Transform = VerifyMiddleware<T, S>;
@ -101,21 +94,19 @@ where
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
ok(VerifyMiddleware(service, self.0, self.1.clone())) ready(Ok(VerifyMiddleware(service, self.0, self.1.clone())))
} }
} }
type FutResult<T, E> = dyn Future<Output = Result<T, E>>; type FutResult<T, E> = dyn Future<Output = Result<T, E>>;
impl<T, S, B> Service for VerifyMiddleware<T, S> impl<T, S, B> Service<ServiceRequest> for VerifyMiddleware<T, S>
where where
T: DigestVerify + Clone + Send + 'static, T: DigestVerify + Clone + Send + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
+ 'static,
S::Error: 'static, S::Error: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = actix_web::Error; type Error = actix_web::Error;
type Future = Pin<Box<FutResult<Self::Response, Self::Error>>>; type Future = Pin<Box<FutResult<Self::Response, Self::Error>>>;
@ -130,7 +121,7 @@ where
Some(vec) => vec, Some(vec) => vec,
None => { None => {
warn!("Digest header could not be parsed"); warn!("Digest header could not be parsed");
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
}; };
let payload = req.take_payload(); let payload = req.take_payload();
@ -138,7 +129,7 @@ where
let (tx, rx) = mpsc::channel(1); let (tx, rx) = mpsc::channel(1);
let f1 = verify_payload(vec, self.2.clone(), payload, tx); let f1 = verify_payload(vec, self.2.clone(), payload, tx);
let payload: Pin<Box<dyn Stream<Item = Result<Bytes, PayloadError>> + 'static>> = let payload: Pin<Box<dyn Stream<Item = Result<web::Bytes, PayloadError>> + 'static>> =
Box::pin(rx.map(Ok)); Box::pin(rx.map(Ok));
req.set_payload(payload.into()); req.set_payload(payload.into());
req.extensions_mut().insert(DigestVerified); req.extensions_mut().insert(DigestVerified);
@ -150,7 +141,7 @@ where
f2.await f2.await
}) })
} else if self.1 { } else if self.1 {
Box::pin(err(VerifyError.into())) Box::pin(ready(Err(VerifyError.into())))
} else { } else {
Box::pin(self.0.call(req)) Box::pin(self.0.call(req))
} }
@ -161,7 +152,7 @@ async fn verify_payload<T>(
vec: Vec<DigestPart>, vec: Vec<DigestPart>,
mut verify_digest: T, mut verify_digest: T,
mut payload: Payload, mut payload: Payload,
mut tx: mpsc::Sender<Bytes>, mut tx: mpsc::Sender<web::Bytes>,
) -> Result<(), actix_web::Error> ) -> Result<(), actix_web::Error>
where where
T: DigestVerify + Clone + Send + 'static, T: DigestVerify + Clone + Send + 'static,

View file

@ -6,10 +6,9 @@ use actix_web::{
http::StatusCode, http::StatusCode,
Error, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError, Error, FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
}; };
use futures::future::{err, ok, ready, Ready};
use log::{debug, warn}; use log::{debug, warn};
use std::{ use std::{
future::Future, future::{ready, Future, Ready},
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
@ -93,7 +92,7 @@ impl<T, S, B> VerifyMiddleware<T, S>
where where
T: SignatureVerify + 'static, T: SignatureVerify + 'static,
T::Future: 'static, T::Future: 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
fn handle( fn handle(
@ -110,23 +109,23 @@ where
Ok(unverified) => unverified, Ok(unverified) => unverified,
Err(PrepareVerifyError::Expired) => { Err(PrepareVerifyError::Expired) => {
warn!("Header is expired"); warn!("Header is expired");
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
Err(PrepareVerifyError::Missing) => { Err(PrepareVerifyError::Missing) => {
debug!("Header is missing"); debug!("Header is missing");
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
Err(PrepareVerifyError::ParseField(field)) => { Err(PrepareVerifyError::ParseField(field)) => {
debug!("Failed to parse field {}", field); debug!("Failed to parse field {}", field);
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
Err(PrepareVerifyError::Header(e)) => { Err(PrepareVerifyError::Header(e)) => {
debug!("Failed to parse header {}", e); debug!("Failed to parse header {}", e);
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
Err(PrepareVerifyError::Required(req)) => { Err(PrepareVerifyError::Required(req)) => {
debug!("Missing required headers, {:?}", req); debug!("Missing required headers, {:?}", req);
return Box::pin(err(VerifyError.into())); return Box::pin(ready(Err(VerifyError.into())));
} }
}; };
@ -183,15 +182,13 @@ impl FromRequest for SignatureVerified {
} }
} }
impl<T, S, B> Transform<S> for VerifySignature<T> impl<T, S, B> Transform<S, ServiceRequest> for VerifySignature<T>
where where
T: SignatureVerify + Clone + 'static, T: SignatureVerify + Clone + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
+ 'static,
S::Error: 'static, S::Error: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = actix_web::Error; type Error = actix_web::Error;
type Transform = VerifyMiddleware<T, S>; type Transform = VerifyMiddleware<T, S>;
@ -199,26 +196,24 @@ where
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
ok(VerifyMiddleware( ready(Ok(VerifyMiddleware(
service, service,
self.1.clone(), self.1.clone(),
self.2, self.2,
self.3, self.3,
self.0.clone(), self.0.clone(),
)) )))
} }
} }
type FutResult<T, E> = dyn Future<Output = Result<T, E>>; type FutResult<T, E> = dyn Future<Output = Result<T, E>>;
impl<T, S, B> Service for VerifyMiddleware<T, S> impl<T, S, B> Service<ServiceRequest> for VerifyMiddleware<T, S>
where where
T: SignatureVerify + Clone + 'static, T: SignatureVerify + Clone + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
+ 'static,
S::Error: 'static, S::Error: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = actix_web::Error; type Error = actix_web::Error;
type Future = Pin<Box<FutResult<Self::Response, Self::Error>>>; type Future = Pin<Box<FutResult<Self::Response, Self::Error>>>;
@ -241,13 +236,13 @@ where
} }
debug!("Authorization or Signature headers are missing"); debug!("Authorization or Signature headers are missing");
Box::pin(err(VerifyError.into())) Box::pin(ready(Err(VerifyError.into())))
} else if self.3 { } else if self.3 {
debug!("Headers are missing but Optional is true, continuing"); debug!("Headers are missing but Optional is true, continuing");
Box::pin(self.0.call(req)) Box::pin(self.0.call(req))
} else { } else {
debug!("Authorization or Signature headers are missing"); debug!("Authorization or Signature headers are missing");
Box::pin(err(VerifyError.into())) Box::pin(ready(Err(VerifyError.into())))
} }
} }
} }