tower_http/decompression/request/
mod.rs

1pub(super) mod future;
2pub(super) mod layer;
3pub(super) mod service;
4
5#[cfg(test)]
6mod tests {
7    use super::service::RequestDecompression;
8    use crate::decompression::DecompressionBody;
9    use crate::test_helpers::Body;
10    use flate2::{write::GzEncoder, Compression};
11    use http::{header, Request, Response, StatusCode};
12    use http_body_util::BodyExt;
13    use std::{convert::Infallible, io::Write};
14    use tower::{service_fn, Service, ServiceExt};
15
16    #[tokio::test]
17    async fn decompress_accepted_encoding() {
18        let req = request_gzip();
19        let mut svc = RequestDecompression::new(service_fn(assert_request_is_decompressed));
20        let _ = svc.ready().await.unwrap().call(req).await.unwrap();
21    }
22
23    #[tokio::test]
24    async fn support_unencoded_body() {
25        let req = Request::builder().body(Body::from("Hello?")).unwrap();
26        let mut svc = RequestDecompression::new(service_fn(assert_request_is_decompressed));
27        let _ = svc.ready().await.unwrap().call(req).await.unwrap();
28    }
29
30    #[tokio::test]
31    async fn unaccepted_content_encoding_returns_unsupported_media_type() {
32        let req = request_gzip();
33        let mut svc = RequestDecompression::new(service_fn(should_not_be_called)).gzip(false);
34        let res = svc.ready().await.unwrap().call(req).await.unwrap();
35        assert_eq!(StatusCode::UNSUPPORTED_MEDIA_TYPE, res.status());
36    }
37
38    #[tokio::test]
39    async fn pass_through_unsupported_encoding_when_enabled() {
40        let req = request_gzip();
41        let mut svc = RequestDecompression::new(service_fn(assert_request_is_passed_through))
42            .pass_through_unaccepted(true)
43            .gzip(false);
44        let _ = svc.ready().await.unwrap().call(req).await.unwrap();
45    }
46
47    async fn assert_request_is_decompressed(
48        req: Request<DecompressionBody<Body>>,
49    ) -> Result<Response<Body>, Infallible> {
50        let (parts, mut body) = req.into_parts();
51        let body = read_body(&mut body).await;
52
53        assert_eq!(body, b"Hello?");
54        assert!(!parts.headers.contains_key(header::CONTENT_ENCODING));
55
56        Ok(Response::new(Body::from("Hello, World!")))
57    }
58
59    async fn assert_request_is_passed_through(
60        req: Request<DecompressionBody<Body>>,
61    ) -> Result<Response<Body>, Infallible> {
62        let (parts, mut body) = req.into_parts();
63        let body = read_body(&mut body).await;
64
65        assert_ne!(body, b"Hello?");
66        assert!(parts.headers.contains_key(header::CONTENT_ENCODING));
67
68        Ok(Response::new(Body::empty()))
69    }
70
71    async fn should_not_be_called(
72        _: Request<DecompressionBody<Body>>,
73    ) -> Result<Response<Body>, Infallible> {
74        panic!("Inner service should not be called");
75    }
76
77    fn request_gzip() -> Request<Body> {
78        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
79        encoder.write_all(b"Hello?").unwrap();
80        let body = encoder.finish().unwrap();
81        Request::builder()
82            .header(header::CONTENT_ENCODING, "gzip")
83            .body(Body::from(body))
84            .unwrap()
85    }
86
87    async fn read_body(body: &mut DecompressionBody<Body>) -> Vec<u8> {
88        body.collect().await.unwrap().to_bytes().to_vec()
89    }
90}