http_msgsign_draft/digest/
request.rs1use super::{BodyDigest, ContentHasher, DigestError};
2use crate::digest::Digest;
3use crate::digest::header::{self, DIGEST};
4use bytes::Bytes;
5use http::Request;
6use http_body_util::combinators::BoxBody;
7use http_body_util::{BodyExt, Full};
8
9impl<B> Digest for Request<B>
10where
11 B: http_body::Body + Send,
12 B::Data: Send,
13{
14 type Error = DigestError;
15 type Content = Request<BoxBody<Bytes, DigestError>>;
16
17 async fn digest<H: ContentHasher>(self) -> Result<Self::Content, Self::Error> {
18 let (mut parts, body) = self.into_parts();
19 let actual = body.digest::<H>().await.map_err(|_e| DigestError::Body)?;
20
21 let body = Full::new(actual.body)
22 .map_err(|infallible| match infallible {})
23 .boxed();
24
25 parts.headers.insert(
26 DIGEST,
27 format!("{}={}", H::DIGEST_ALG, actual.digest.to_base64())
28 .parse()
29 .unwrap(),
30 );
31
32 Ok(Request::from_parts(parts, body))
33 }
34
35 async fn verify_digest<H: ContentHasher>(self) -> Result<Self::Content, Self::Error> {
36 let (parts, body) = self.into_parts();
37 let expect = header::Digest::from_header(&parts.headers)?;
38
39 if expect.alg != H::DIGEST_ALG {
40 return Err(DigestError::AlgorithmNotSupported);
41 };
42
43 let actual = body.digest::<H>().await.map_err(|_e| DigestError::Body)?;
44
45 if actual.digest != expect.digest {
46 return Err(DigestError::Mismatch);
47 }
48
49 let body = Full::new(actual.body)
50 .map_err(|infallible| match infallible {})
51 .boxed();
52
53 Ok(Request::from_parts(parts, body))
54 }
55}