Skip to main content

http_msgsign_draft/digest/
request.rs

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