mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-11-25 10:51:01 +00:00
Update to actix-web 4.0 beta.1
This commit is contained in:
parent
894001efe6
commit
d04612a729
4 changed files with 33 additions and 47 deletions
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue