1 mod support;
2 use support::*;
3 
4 use std::io::Write;
5 
6 #[tokio::test]
gzip_response()7 async fn gzip_response() {
8     gzip_case(10_000, 4096).await;
9 }
10 
11 #[tokio::test]
gzip_single_byte_chunks()12 async fn gzip_single_byte_chunks() {
13     gzip_case(10, 1).await;
14 }
15 
16 #[tokio::test]
test_gzip_empty_body()17 async fn test_gzip_empty_body() {
18     let server = server::http(move |req| async move {
19         assert_eq!(req.method(), "HEAD");
20 
21         http::Response::builder()
22             .header("content-encoding", "gzip")
23             .header("content-length", 100)
24             .body(Default::default())
25             .unwrap()
26     });
27 
28     let client = reqwest::Client::new();
29     let res = client
30         .head(&format!("http://{}/gzip", server.addr()))
31         .send()
32         .await
33         .unwrap();
34 
35     let body = res.text().await.unwrap();
36 
37     assert_eq!(body, "");
38 }
39 
40 #[tokio::test]
test_accept_header_is_not_changed_if_set()41 async fn test_accept_header_is_not_changed_if_set() {
42     let server = server::http(move |req| async move {
43         assert_eq!(req.headers()["accept"], "application/json");
44         assert!(req.headers()["accept-encoding"]
45             .to_str()
46             .unwrap()
47             .contains("gzip"));
48         http::Response::default()
49     });
50 
51     let client = reqwest::Client::new();
52 
53     let res = client
54         .get(&format!("http://{}/accept", server.addr()))
55         .header(
56             reqwest::header::ACCEPT,
57             reqwest::header::HeaderValue::from_static("application/json"),
58         )
59         .send()
60         .await
61         .unwrap();
62 
63     assert_eq!(res.status(), reqwest::StatusCode::OK);
64 }
65 
66 #[tokio::test]
test_accept_encoding_header_is_not_changed_if_set()67 async fn test_accept_encoding_header_is_not_changed_if_set() {
68     let server = server::http(move |req| async move {
69         assert_eq!(req.headers()["accept"], "*/*");
70         assert_eq!(req.headers()["accept-encoding"], "identity");
71         http::Response::default()
72     });
73 
74     let client = reqwest::Client::new();
75 
76     let res = client
77         .get(&format!("http://{}/accept-encoding", server.addr()))
78         .header(
79             reqwest::header::ACCEPT_ENCODING,
80             reqwest::header::HeaderValue::from_static("identity"),
81         )
82         .send()
83         .await
84         .unwrap();
85 
86     assert_eq!(res.status(), reqwest::StatusCode::OK);
87 }
88 
gzip_case(response_size: usize, chunk_size: usize)89 async fn gzip_case(response_size: usize, chunk_size: usize) {
90     use futures_util::stream::StreamExt;
91 
92     let content: String = (0..response_size)
93         .into_iter()
94         .map(|i| format!("test {}", i))
95         .collect();
96     let mut encoder = libflate::gzip::Encoder::new(Vec::new()).unwrap();
97     match encoder.write(content.as_bytes()) {
98         Ok(n) => assert!(n > 0, "Failed to write to encoder."),
99         _ => panic!("Failed to gzip encode string."),
100     };
101 
102     let gzipped_content = encoder.finish().into_result().unwrap();
103 
104     let mut response = format!(
105         "\
106          HTTP/1.1 200 OK\r\n\
107          Server: test-accept\r\n\
108          Content-Encoding: gzip\r\n\
109          Content-Length: {}\r\n\
110          \r\n",
111         &gzipped_content.len()
112     )
113     .into_bytes();
114     response.extend(&gzipped_content);
115 
116     let server = server::http(move |req| {
117         assert!(req.headers()["accept-encoding"]
118             .to_str()
119             .unwrap()
120             .contains("gzip"));
121 
122         let gzipped = gzipped_content.clone();
123         async move {
124             let len = gzipped.len();
125             let stream =
126                 futures_util::stream::unfold((gzipped, 0), move |(gzipped, pos)| async move {
127                     let chunk = gzipped.chunks(chunk_size).nth(pos)?.to_vec();
128 
129                     Some((chunk, (gzipped, pos + 1)))
130                 });
131 
132             let body = hyper::Body::wrap_stream(stream.map(Ok::<_, std::convert::Infallible>));
133 
134             http::Response::builder()
135                 .header("content-encoding", "gzip")
136                 .header("content-length", len)
137                 .body(body)
138                 .unwrap()
139         }
140     });
141 
142     let client = reqwest::Client::new();
143 
144     let res = client
145         .get(&format!("http://{}/gzip", server.addr()))
146         .send()
147         .await
148         .expect("response");
149 
150     let body = res.text().await.expect("text");
151     assert_eq!(body, content);
152 }
153