Skip to main content

http_msgsign_draft/digest/
response.rs

1use 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}