1 #![cfg(not(target_arch = "wasm32"))]
2 mod support;
3 use futures_util::stream::StreamExt;
4 use support::*;
5 
6 #[tokio::test]
text_part()7 async fn text_part() {
8     let _ = env_logger::try_init();
9 
10     let form = reqwest::multipart::Form::new().text("foo", "bar");
11 
12     let expected_body = format!(
13         "\
14          --{0}\r\n\
15          Content-Disposition: form-data; name=\"foo\"\r\n\r\n\
16          bar\r\n\
17          --{0}--\r\n\
18          ",
19         form.boundary()
20     );
21 
22     let ct = format!("multipart/form-data; boundary={}", form.boundary());
23 
24     let server = server::http(move |mut req| {
25         let ct = ct.clone();
26         let expected_body = expected_body.clone();
27         async move {
28             assert_eq!(req.method(), "POST");
29             assert_eq!(req.headers()["content-type"], ct);
30             assert_eq!(
31                 req.headers()["content-length"],
32                 expected_body.len().to_string()
33             );
34 
35             let mut full: Vec<u8> = Vec::new();
36             while let Some(item) = req.body_mut().next().await {
37                 full.extend(&*item.unwrap());
38             }
39 
40             assert_eq!(full, expected_body.as_bytes());
41 
42             http::Response::default()
43         }
44     });
45 
46     let url = format!("http://{}/multipart/1", server.addr());
47 
48     let res = reqwest::Client::new()
49         .post(&url)
50         .multipart(form)
51         .send()
52         .await
53         .unwrap();
54 
55     assert_eq!(res.url().as_str(), &url);
56     assert_eq!(res.status(), reqwest::StatusCode::OK);
57 }
58 
59 #[cfg(feature = "stream")]
60 #[tokio::test]
stream_part()61 async fn stream_part() {
62     use futures_util::{future, stream};
63 
64     let _ = env_logger::try_init();
65 
66     let stream = reqwest::Body::wrap_stream(stream::once(future::ready(Ok::<_, reqwest::Error>(
67         "part1 part2".to_owned(),
68     ))));
69     let part = reqwest::multipart::Part::stream(stream);
70 
71     let form = reqwest::multipart::Form::new()
72         .text("foo", "bar")
73         .part("part_stream", part);
74 
75     let expected_body = format!(
76         "\
77          --{0}\r\n\
78          Content-Disposition: form-data; name=\"foo\"\r\n\
79          \r\n\
80          bar\r\n\
81          --{0}\r\n\
82          Content-Disposition: form-data; name=\"part_stream\"\r\n\
83          \r\n\
84          part1 part2\r\n\
85          --{0}--\r\n\
86          ",
87         form.boundary()
88     );
89 
90     let ct = format!("multipart/form-data; boundary={}", form.boundary());
91 
92     let server = server::http(move |mut req| {
93         let ct = ct.clone();
94         let expected_body = expected_body.clone();
95         async move {
96             assert_eq!(req.method(), "POST");
97             assert_eq!(req.headers()["content-type"], ct);
98             assert_eq!(req.headers()["transfer-encoding"], "chunked");
99 
100             let mut full: Vec<u8> = Vec::new();
101             while let Some(item) = req.body_mut().next().await {
102                 full.extend(&*item.unwrap());
103             }
104 
105             assert_eq!(full, expected_body.as_bytes());
106 
107             http::Response::default()
108         }
109     });
110 
111     let url = format!("http://{}/multipart/1", server.addr());
112 
113     let client = reqwest::Client::new();
114 
115     let res = client
116         .post(&url)
117         .multipart(form)
118         .send()
119         .await
120         .expect("Failed to post multipart");
121     assert_eq!(res.url().as_str(), &url);
122     assert_eq!(res.status(), reqwest::StatusCode::OK);
123 }
124 
125 #[cfg(feature = "blocking")]
126 #[test]
blocking_file_part()127 fn blocking_file_part() {
128     let _ = env_logger::try_init();
129 
130     let form = reqwest::blocking::multipart::Form::new()
131         .file("foo", "Cargo.lock")
132         .unwrap();
133 
134     let fcontents = std::fs::read_to_string("Cargo.lock").unwrap();
135 
136     let expected_body = format!(
137         "\
138          --{0}\r\n\
139          Content-Disposition: form-data; name=\"foo\"; filename=\"Cargo.lock\"\r\n\
140          Content-Type: application/octet-stream\r\n\r\n\
141          {1}\r\n\
142          --{0}--\r\n\
143          ",
144         form.boundary(),
145         fcontents
146     );
147 
148     let ct = format!("multipart/form-data; boundary={}", form.boundary());
149 
150     let server = server::http(move |mut req| {
151         let ct = ct.clone();
152         let expected_body = expected_body.clone();
153         async move {
154             assert_eq!(req.method(), "POST");
155             assert_eq!(req.headers()["content-type"], ct);
156             // files know their exact size
157             assert_eq!(
158                 req.headers()["content-length"],
159                 expected_body.len().to_string()
160             );
161 
162             let mut full: Vec<u8> = Vec::new();
163             while let Some(item) = req.body_mut().next().await {
164                 full.extend(&*item.unwrap());
165             }
166 
167             assert_eq!(full, expected_body.as_bytes());
168 
169             http::Response::default()
170         }
171     });
172 
173     let url = format!("http://{}/multipart/2", server.addr());
174 
175     let res = reqwest::blocking::Client::new()
176         .post(&url)
177         .multipart(form)
178         .send()
179         .unwrap();
180 
181     assert_eq!(res.url().as_str(), &url);
182     assert_eq!(res.status(), reqwest::StatusCode::OK);
183 }
184