reqwest_wasm/wasm/
body.rs1#[cfg(feature = "multipart")]
2use super::multipart::Form;
3use bytes::Bytes;
5use js_sys::Uint8Array;
6use std::fmt;
7use wasm_bindgen::JsValue;
8
9pub struct Body {
17 inner: Inner,
18}
19
20enum Inner {
21 Bytes(Bytes),
22 #[cfg(feature = "multipart")]
24 MultipartForm(Form),
25 #[cfg(feature = "multipart")]
27 MultipartPart(Bytes),
28}
29
30impl Body {
31 #[inline]
35 pub fn as_bytes(&self) -> Option<&[u8]> {
36 match &self.inner {
37 Inner::Bytes(bytes) => Some(bytes.as_ref()),
38 #[cfg(feature = "multipart")]
39 Inner::MultipartForm(_) => None,
40 #[cfg(feature = "multipart")]
41 Inner::MultipartPart(bytes) => Some(bytes.as_ref()),
42 }
43 }
44 pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
45 match &self.inner {
46 Inner::Bytes(body_bytes) => {
47 let body_bytes: &[u8] = body_bytes.as_ref();
48 let body_uint8_array: Uint8Array = body_bytes.into();
49 let js_value: &JsValue = body_uint8_array.as_ref();
50 Ok(js_value.to_owned())
51 }
52 #[cfg(feature = "multipart")]
53 Inner::MultipartForm(form) => {
54 let form_data = form.to_form_data()?;
55 let js_value: &JsValue = form_data.as_ref();
56 Ok(js_value.to_owned())
57 }
58 #[cfg(feature = "multipart")]
59 Inner::MultipartPart(body_bytes) => {
60 let body_bytes: &[u8] = body_bytes.as_ref();
61 let body_uint8_array: Uint8Array = body_bytes.into();
62 let body_array = js_sys::Array::new();
63 body_array.push(&body_uint8_array);
64 let js_value: &JsValue = body_array.as_ref();
65 Ok(js_value.to_owned())
66 }
67 }
68 }
69
70 #[inline]
71 #[cfg(feature = "multipart")]
72 pub(crate) fn from_form(f: Form) -> Body {
73 Self {
74 inner: Inner::MultipartForm(f),
75 }
76 }
77
78 #[cfg(feature = "multipart")]
80 pub(crate) fn into_part(self) -> Body {
81 match self.inner {
82 Inner::Bytes(bytes) => Self {
83 inner: Inner::MultipartPart(bytes),
84 },
85 Inner::MultipartForm(form) => Self {
86 inner: Inner::MultipartForm(form),
87 },
88 Inner::MultipartPart(bytes) => Self {
89 inner: Inner::MultipartPart(bytes),
90 },
91 }
92 }
93
94 pub(crate) fn is_empty(&self) -> bool {
95 match &self.inner {
96 Inner::Bytes(bytes) => bytes.is_empty(),
97 #[cfg(feature = "multipart")]
98 Inner::MultipartForm(form) => form.is_empty(),
99 #[cfg(feature = "multipart")]
100 Inner::MultipartPart(bytes) => bytes.is_empty(),
101 }
102 }
103
104 pub(crate) fn try_clone(&self) -> Option<Body> {
105 match &self.inner {
106 Inner::Bytes(bytes) => Some(Self {
107 inner: Inner::Bytes(bytes.clone()),
108 }),
109 #[cfg(feature = "multipart")]
110 Inner::MultipartForm(_) => None,
111 #[cfg(feature = "multipart")]
112 Inner::MultipartPart(bytes) => Some(Self {
113 inner: Inner::MultipartPart(bytes.clone()),
114 }),
115 }
116 }
117}
118
119impl From<Bytes> for Body {
120 #[inline]
121 fn from(bytes: Bytes) -> Body {
122 Body {
123 inner: Inner::Bytes(bytes),
124 }
125 }
126}
127
128impl From<Vec<u8>> for Body {
129 #[inline]
130 fn from(vec: Vec<u8>) -> Body {
131 Body {
132 inner: Inner::Bytes(vec.into()),
133 }
134 }
135}
136
137impl From<&'static [u8]> for Body {
138 #[inline]
139 fn from(s: &'static [u8]) -> Body {
140 Body {
141 inner: Inner::Bytes(Bytes::from_static(s)),
142 }
143 }
144}
145
146impl From<String> for Body {
147 #[inline]
148 fn from(s: String) -> Body {
149 Body {
150 inner: Inner::Bytes(s.into()),
151 }
152 }
153}
154
155impl From<&'static str> for Body {
156 #[inline]
157 fn from(s: &'static str) -> Body {
158 s.as_bytes().into()
159 }
160}
161
162impl fmt::Debug for Body {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 f.debug_struct("Body").finish()
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use crate::Body;
171 use js_sys::Uint8Array;
172 use wasm_bindgen::prelude::*;
173 use wasm_bindgen_test::*;
174
175 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
176
177 #[wasm_bindgen]
178 extern "C" {
179 #[wasm_bindgen(js_namespace = console)]
182 fn log(s: String);
183 }
184
185 #[wasm_bindgen_test]
186 async fn test_body() {
187 let body = Body::from("TEST");
188 assert_eq!([84, 69, 83, 84], body.as_bytes().unwrap());
189 }
190
191 #[wasm_bindgen_test]
192 async fn test_body_js_static_str() {
193 let body_value = "TEST";
194 let body = Body::from(body_value);
195
196 let mut init = web_sys::RequestInit::new();
197 init.method("POST");
198 init.body(Some(
199 body.to_js_value()
200 .expect("could not convert body to JsValue")
201 .as_ref(),
202 ));
203
204 let js_req = web_sys::Request::new_with_str_and_init("", &init)
205 .expect("could not create JS request");
206 let text_promise = js_req.text().expect("could not get text promise");
207 let text = crate::wasm::promise::<JsValue>(text_promise)
208 .await
209 .expect("could not get request body as text");
210
211 assert_eq!(text.as_string().expect("text is not a string"), body_value);
212 }
213 #[wasm_bindgen_test]
214 async fn test_body_js_string() {
215 let body_value = "TEST".to_string();
216 let body = Body::from(body_value.clone());
217
218 let mut init = web_sys::RequestInit::new();
219 init.method("POST");
220 init.body(Some(
221 body.to_js_value()
222 .expect("could not convert body to JsValue")
223 .as_ref(),
224 ));
225
226 let js_req = web_sys::Request::new_with_str_and_init("", &init)
227 .expect("could not create JS request");
228 let text_promise = js_req.text().expect("could not get text promise");
229 let text = crate::wasm::promise::<JsValue>(text_promise)
230 .await
231 .expect("could not get request body as text");
232
233 assert_eq!(text.as_string().expect("text is not a string"), body_value);
234 }
235
236 #[wasm_bindgen_test]
237 async fn test_body_js_static_u8_slice() {
238 let body_value: &'static [u8] = b"\x00\x42";
239 let body = Body::from(body_value);
240
241 let mut init = web_sys::RequestInit::new();
242 init.method("POST");
243 init.body(Some(
244 body.to_js_value()
245 .expect("could not convert body to JsValue")
246 .as_ref(),
247 ));
248
249 let js_req = web_sys::Request::new_with_str_and_init("", &init)
250 .expect("could not create JS request");
251
252 let array_buffer_promise = js_req
253 .array_buffer()
254 .expect("could not get array_buffer promise");
255 let array_buffer = crate::wasm::promise::<JsValue>(array_buffer_promise)
256 .await
257 .expect("could not get request body as array buffer");
258
259 let v = Uint8Array::new(&array_buffer).to_vec();
260
261 assert_eq!(v, body_value);
262 }
263
264 #[wasm_bindgen_test]
265 async fn test_body_js_vec_u8() {
266 let body_value = vec![0u8, 42];
267 let body = Body::from(body_value.clone());
268
269 let mut init = web_sys::RequestInit::new();
270 init.method("POST");
271 init.body(Some(
272 body.to_js_value()
273 .expect("could not convert body to JsValue")
274 .as_ref(),
275 ));
276
277 let js_req = web_sys::Request::new_with_str_and_init("", &init)
278 .expect("could not create JS request");
279
280 let array_buffer_promise = js_req
281 .array_buffer()
282 .expect("could not get array_buffer promise");
283 let array_buffer = crate::wasm::promise::<JsValue>(array_buffer_promise)
284 .await
285 .expect("could not get request body as array buffer");
286
287 let v = Uint8Array::new(&array_buffer).to_vec();
288
289 assert_eq!(v, body_value);
290 }
291}