1use std::fs::File;
2use std::io::{self, Read, Stdin};
3use std::net::TcpStream;
4
5use crate::body::{Body, BodyReader};
6use crate::util::private::Private;
7use crate::{http, Error};
8
9pub struct SendBody<'a> {
20 inner: BodyInner<'a>,
21 size: Option<Result<u64, Error>>,
22 ended: bool,
23 content_type: Option<HeaderValue>,
24}
25
26impl<'a> SendBody<'a> {
27 pub fn none() -> SendBody<'static> {
29 (None, BodyInner::None).into()
30 }
31
32 pub fn from_reader(reader: &'a mut dyn Read) -> SendBody<'a> {
34 (None, BodyInner::Reader(reader)).into()
35 }
36
37 pub fn from_owned_reader(reader: impl Read + 'static) -> SendBody<'static> {
39 (None, BodyInner::OwnedReader(Box::new(reader))).into()
40 }
41
42 #[cfg(feature = "multipart")]
43 pub(crate) fn from_file(file: File) -> SendBody<'static> {
44 let size = lazy_file_size(&file);
45 SendBody {
46 inner: BodyInner::OwnedReader(Box::new(file)),
47 size: Some(size),
48 ended: false,
49 content_type: None,
50 }
51 }
52
53 #[cfg(feature = "json")]
55 pub fn from_json(
56 value: &impl serde::ser::Serialize,
57 ) -> Result<SendBody<'static>, crate::Error> {
58 let json = serde_json::to_vec_pretty(value)?;
59 let len = json.len() as u64;
60 let body: SendBody = (Some(len), BodyInner::ByteVec(io::Cursor::new(json))).into();
61 let body =
62 body.with_content_type(HeaderValue::from_static("application/json; charset=utf-8"));
63 Ok(body)
64 }
65
66 pub(crate) fn with_content_type(mut self, content_type: HeaderValue) -> Self {
67 self.content_type = Some(content_type);
68 self
69 }
70
71 pub(crate) fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
72 let n = match &mut self.inner {
73 BodyInner::None => {
74 return Ok(0);
75 }
76 BodyInner::ByteSlice(v) => {
77 let max = v.len().min(buf.len());
78
79 buf[..max].copy_from_slice(&v[..max]);
80 *v = &v[max..];
81
82 Ok(max)
83 }
84 #[cfg(feature = "json")]
85 BodyInner::ByteVec(v) => v.read(buf),
86 BodyInner::Reader(v) => v.read(buf),
87 BodyInner::OwnedReader(v) => v.read(buf),
88 BodyInner::Body(v) => v.read(buf),
89 }?;
90
91 if n == 0 {
92 self.ended = true;
93 }
94
95 Ok(n)
96 }
97
98 pub(crate) fn body_mode(&mut self) -> Result<BodyMode, Error> {
99 let size = match self.size {
101 None => None,
102 Some(Ok(v)) => Some(v),
103 Some(Err(_)) => {
104 return Err(self.size.take().unwrap().unwrap_err());
106 }
107 };
108
109 match &self.inner {
110 BodyInner::None => return Ok(BodyMode::NoBody),
111 BodyInner::Body(v) => return Ok(v.body_mode()),
112
113 BodyInner::ByteSlice(_) => {}
115 #[cfg(feature = "json")]
116 BodyInner::ByteVec(_) => {}
117 BodyInner::Reader(_) => {}
118 BodyInner::OwnedReader(_) => {}
119 };
120
121 let mode = if let Some(size) = size {
124 BodyMode::LengthDelimited(size)
125 } else {
126 BodyMode::Chunked
127 };
128
129 Ok(mode)
130 }
131
132 pub fn into_reader(self) -> impl Sized + io::Read + 'a {
163 ReadAdapter(self)
164 }
165
166 #[cfg(feature = "multipart")]
167 pub(crate) fn from_bytes<'b>(bytes: &'b [u8]) -> SendBody<'b> {
168 SendBody {
169 inner: BodyInner::ByteSlice(bytes),
170 size: Some(Ok(bytes.len() as u64)),
171 ended: false,
172 content_type: None,
173 }
174 }
175
176 #[cfg(feature = "multipart")]
177 pub(crate) fn size(&self) -> Option<u64> {
178 self.size.as_ref().and_then(|r| r.as_ref().ok()).copied()
179 }
180
181 pub(crate) fn take_content_type(&mut self) -> Option<HeaderValue> {
183 self.content_type.take()
184 }
185}
186
187struct ReadAdapter<'a>(SendBody<'a>);
188
189impl<'a> io::Read for ReadAdapter<'a> {
190 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
191 self.0.read(buf)
192 }
193}
194
195use http::Response;
196use ureq_proto::http::HeaderValue;
197use ureq_proto::BodyMode;
198
199pub trait AsSendBody: Private {
249 #[doc(hidden)]
250 fn as_body(&mut self) -> SendBody;
251}
252
253impl<'a> Private for SendBody<'a> {}
254impl<'a> AsSendBody for SendBody<'a> {
255 fn as_body(&mut self) -> SendBody {
256 SendBody {
257 inner: match &mut self.inner {
258 BodyInner::None => BodyInner::None,
259 BodyInner::ByteSlice(v) => BodyInner::ByteSlice(v),
260 #[cfg(feature = "json")]
261 BodyInner::ByteVec(v) => BodyInner::ByteSlice(v.get_ref()),
262 BodyInner::Reader(v) => BodyInner::Reader(v),
263 BodyInner::Body(v) => BodyInner::Reader(v),
264 BodyInner::OwnedReader(v) => BodyInner::Reader(v),
265 },
266 size: self.size.take(),
267 ended: self.ended,
268 content_type: self.content_type.take(),
269 }
270 }
271}
272
273pub(crate) enum BodyInner<'a> {
274 None,
275 ByteSlice(&'a [u8]),
276 #[cfg(feature = "json")]
277 ByteVec(io::Cursor<Vec<u8>>),
278 Body(Box<BodyReader<'a>>),
279 Reader(&'a mut dyn Read),
280 OwnedReader(Box<dyn Read>),
281}
282
283impl Private for &[u8] {}
284impl AsSendBody for &[u8] {
285 fn as_body(&mut self) -> SendBody {
286 let inner = BodyInner::ByteSlice(self);
287 (Some(self.len() as u64), inner).into()
288 }
289}
290
291impl Private for &str {}
292impl AsSendBody for &str {
293 fn as_body(&mut self) -> SendBody {
294 let inner = BodyInner::ByteSlice((*self).as_ref());
295 (Some(self.len() as u64), inner).into()
296 }
297}
298
299impl Private for String {}
300impl AsSendBody for String {
301 fn as_body(&mut self) -> SendBody {
302 let inner = BodyInner::ByteSlice((*self).as_ref());
303 (Some(self.len() as u64), inner).into()
304 }
305}
306
307impl Private for Vec<u8> {}
308impl AsSendBody for Vec<u8> {
309 fn as_body(&mut self) -> SendBody {
310 let inner = BodyInner::ByteSlice((*self).as_ref());
311 (Some(self.len() as u64), inner).into()
312 }
313}
314
315impl Private for &String {}
316impl AsSendBody for &String {
317 fn as_body(&mut self) -> SendBody {
318 let inner = BodyInner::ByteSlice((*self).as_ref());
319 (Some(self.len() as u64), inner).into()
320 }
321}
322
323impl Private for &Vec<u8> {}
324impl AsSendBody for &Vec<u8> {
325 fn as_body(&mut self) -> SendBody {
326 let inner = BodyInner::ByteSlice((*self).as_ref());
327 (Some(self.len() as u64), inner).into()
328 }
329}
330
331impl Private for &File {}
332impl AsSendBody for &File {
333 fn as_body(&mut self) -> SendBody {
334 let size = lazy_file_size(self);
335 SendBody {
336 inner: BodyInner::Reader(self),
337 size: Some(size),
338 ended: false,
339 content_type: None,
340 }
341 }
342}
343
344impl Private for File {}
345impl AsSendBody for File {
346 fn as_body(&mut self) -> SendBody {
347 let size = lazy_file_size(self);
348 SendBody {
349 inner: BodyInner::Reader(self),
350 size: Some(size),
351 ended: false,
352 content_type: None,
353 }
354 }
355}
356
357fn lazy_file_size(file: &File) -> Result<u64, Error> {
358 match file.metadata() {
359 Ok(v) => Ok(v.len()),
360 Err(e) => Err(e.into()),
361 }
362}
363
364impl Private for &TcpStream {}
365impl AsSendBody for &TcpStream {
366 fn as_body(&mut self) -> SendBody {
367 (None, BodyInner::Reader(self)).into()
368 }
369}
370
371impl Private for TcpStream {}
372impl AsSendBody for TcpStream {
373 fn as_body(&mut self) -> SendBody {
374 (None, BodyInner::Reader(self)).into()
375 }
376}
377
378impl Private for Stdin {}
379impl AsSendBody for Stdin {
380 fn as_body(&mut self) -> SendBody {
381 (None, BodyInner::Reader(self)).into()
382 }
383}
384
385#[cfg(target_family = "unix")]
389use std::os::unix::net::UnixStream;
390
391#[cfg(target_family = "unix")]
392impl Private for UnixStream {}
393#[cfg(target_family = "unix")]
394impl AsSendBody for UnixStream {
395 fn as_body(&mut self) -> SendBody {
396 (None, BodyInner::Reader(self)).into()
397 }
398}
399
400impl<'a> From<(Option<u64>, BodyInner<'a>)> for SendBody<'a> {
401 fn from((size, inner): (Option<u64>, BodyInner<'a>)) -> Self {
402 SendBody {
403 inner,
404 size: size.map(Ok),
405 ended: false,
406 content_type: None,
407 }
408 }
409}
410
411impl Private for Body {}
412impl AsSendBody for Body {
413 fn as_body(&mut self) -> SendBody {
414 let size = self.content_length();
415 (size, BodyInner::Body(Box::new(self.as_reader()))).into()
416 }
417}
418
419impl Private for Response<Body> {}
420impl AsSendBody for Response<Body> {
421 fn as_body(&mut self) -> SendBody {
422 let size = self.body().content_length();
423 (size, BodyInner::Body(Box::new(self.body_mut().as_reader()))).into()
424 }
425}
426
427impl<const N: usize> Private for &[u8; N] {}
428impl<const N: usize> AsSendBody for &[u8; N] {
429 fn as_body(&mut self) -> SendBody {
430 let inner = BodyInner::ByteSlice((*self).as_ref());
431 (Some(self.len() as u64), inner).into()
432 }
433}
434
435impl Private for () {}
436impl AsSendBody for () {
437 fn as_body(&mut self) -> SendBody {
438 (None, BodyInner::None).into()
439 }
440}