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