[go: up one dir, main page]

ureq/
send_body.rs

1use std::fs::File;
2use std::io::{self, Read, Stdin};
3use std::net::TcpStream;
4
5use crate::body::{Body, BodyReader};
6use crate::http;
7use crate::util::private::Private;
8
9/// Request body for sending data via POST, PUT and PATCH.
10///
11/// Typically not interacted with directly since the trait [`AsSendBody`] is implemented
12/// for the majority of the types of data a user might want to send to a remote server.
13/// That means if you want to send things like `String`, `&str` or `[u8]`, they can be
14/// used directly. See documentation for [`AsSendBody`].
15///
16/// The exception is when using [`Read`] trait bodies, in which case we wrap the request
17/// body directly. See below [`SendBody::from_reader`].
18///
19pub struct SendBody<'a> {
20    inner: BodyInner<'a>,
21    ended: bool,
22}
23
24impl<'a> SendBody<'a> {
25    /// Creates an empty body.
26    pub fn none() -> SendBody<'static> {
27        BodyInner::None.into()
28    }
29
30    /// Creates a body from a shared [`Read`] impl.
31    pub fn from_reader(reader: &'a mut dyn Read) -> SendBody<'a> {
32        BodyInner::Reader(reader).into()
33    }
34
35    /// Creates a body from an owned [`Read]` impl.
36    pub fn from_owned_reader(reader: impl Read + 'static) -> SendBody<'static> {
37        BodyInner::OwnedReader(Box::new(reader)).into()
38    }
39
40    /// Creates a body to send as JSON from any [`Serialize`](serde::ser::Serialize) value.
41    #[cfg(feature = "json")]
42    pub fn from_json(
43        value: &impl serde::ser::Serialize,
44    ) -> Result<SendBody<'static>, crate::Error> {
45        let json = serde_json::to_vec_pretty(value)?;
46        Ok(BodyInner::ByteVec(io::Cursor::new(json)).into())
47    }
48
49    pub(crate) fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
50        let n = match &mut self.inner {
51            BodyInner::None => {
52                return Ok(0);
53            }
54            BodyInner::ByteSlice(v) => {
55                let max = v.len().min(buf.len());
56
57                buf[..max].copy_from_slice(&v[..max]);
58                *v = &v[max..];
59
60                Ok(max)
61            }
62            #[cfg(feature = "json")]
63            BodyInner::ByteVec(v) => v.read(buf),
64            BodyInner::Reader(v) => v.read(buf),
65            BodyInner::OwnedReader(v) => v.read(buf),
66            BodyInner::Body(v) => v.read(buf),
67        }?;
68
69        if n == 0 {
70            self.ended = true;
71        }
72
73        Ok(n)
74    }
75
76    pub(crate) fn body_mode(&self) -> BodyMode {
77        self.inner.body_mode()
78    }
79
80    /// Turn this `SendBody` into a reader.
81    ///
82    /// This is useful in [`Middleware`][crate::middleware::Middleware] to make changes to the
83    /// body before sending it.
84    ///
85    /// ```
86    /// use ureq::{SendBody, Body};
87    /// use ureq::middleware::MiddlewareNext;
88    /// use ureq::http::{Request, Response, header::HeaderValue};
89    /// use std::io::Read;
90    ///
91    /// fn my_middleware(req: Request<SendBody>, next: MiddlewareNext)
92    ///     -> Result<Response<Body>, ureq::Error> {
93    ///
94    ///     // Take apart the request.
95    ///     let (parts, body) = req.into_parts();
96    ///
97    ///     // Take the first 100 bytes of the incoming send body.
98    ///     let mut reader = body.into_reader().take(100);
99    ///
100    ///     // Create a new SendBody.
101    ///     let new_body = SendBody::from_reader(&mut reader);
102    ///
103    ///     // Reconstitute the request.
104    ///     let req = Request::from_parts(parts, new_body);
105    ///
106    ///     // set my bespoke header and continue the chain
107    ///     next.handle(req)
108    /// }
109    /// ```
110    pub fn into_reader(self) -> impl Sized + io::Read + 'a {
111        ReadAdapter(self)
112    }
113}
114
115struct ReadAdapter<'a>(SendBody<'a>);
116
117impl<'a> io::Read for ReadAdapter<'a> {
118    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
119        self.0.read(buf)
120    }
121}
122
123use http::Response;
124use ureq_proto::BodyMode;
125
126/// Trait for common types to send in POST, PUT or PATCH.
127///
128/// Sending common data types such as `String`, `&str` or `&[u8]` require no further wrapping
129/// and can be sent either by [`RequestBuilder::send()`][crate::RequestBuilder::send] or using the
130/// `http` crate [`Request`][http::Request] directly (see example below).
131///
132/// Implemented for:
133///
134/// * `&str`
135/// * `&String`
136/// * `&Vec<u8>`
137/// * `&File`
138/// * `&TcpStream`
139/// * `&[u8]`
140/// * `Response<Body>`
141/// * `String`
142/// * `Vec<u8>`
143/// * `File`
144/// * `Stdin`
145/// * `TcpStream`
146/// * `UnixStream` (not on windows)
147/// * `&[u8; N]`
148/// * `()`
149///
150/// # Example
151///
152/// These two examples are equivalent.
153///
154/// ```
155/// let data: &[u8] = b"My special request body data";
156///
157/// let response = ureq::post("https://httpbin.org/post")
158///     .send(data)?;
159/// # Ok::<_, ureq::Error>(())
160/// ```
161///
162/// Using `http` crate API
163///
164/// ```
165/// use ureq::http;
166///
167/// let data: &[u8] = b"My special request body data";
168///
169/// let request = http::Request::post("https://httpbin.org/post")
170///     .body(data)?;
171///
172/// let response = ureq::run(request)?;
173/// # Ok::<_, ureq::Error>(())
174/// ```
175pub trait AsSendBody: Private {
176    #[doc(hidden)]
177    fn as_body(&mut self) -> SendBody;
178}
179
180impl<'a> Private for SendBody<'a> {}
181impl<'a> AsSendBody for SendBody<'a> {
182    fn as_body(&mut self) -> SendBody {
183        SendBody {
184            inner: match &mut self.inner {
185                BodyInner::None => BodyInner::None,
186                BodyInner::ByteSlice(v) => BodyInner::ByteSlice(v),
187                #[cfg(feature = "json")]
188                BodyInner::ByteVec(v) => BodyInner::ByteSlice(v.get_ref()),
189                BodyInner::Reader(v) => BodyInner::Reader(v),
190                BodyInner::Body(v) => BodyInner::Reader(v),
191                BodyInner::OwnedReader(v) => BodyInner::Reader(v),
192            },
193            ended: self.ended,
194        }
195    }
196}
197
198pub(crate) enum BodyInner<'a> {
199    None,
200    ByteSlice(&'a [u8]),
201    #[cfg(feature = "json")]
202    ByteVec(io::Cursor<Vec<u8>>),
203    Body(BodyReader<'a>),
204    Reader(&'a mut dyn Read),
205    OwnedReader(Box<dyn Read>),
206}
207
208impl<'a> BodyInner<'a> {
209    pub fn body_mode(&self) -> BodyMode {
210        match self {
211            BodyInner::None => BodyMode::NoBody,
212            BodyInner::ByteSlice(v) => BodyMode::LengthDelimited(v.len() as u64),
213            #[cfg(feature = "json")]
214            BodyInner::ByteVec(v) => BodyMode::LengthDelimited(v.get_ref().len() as u64),
215            BodyInner::Body(v) => v.body_mode(),
216            BodyInner::Reader(_) => BodyMode::Chunked,
217            BodyInner::OwnedReader(_) => BodyMode::Chunked,
218        }
219    }
220}
221
222impl Private for &[u8] {}
223impl AsSendBody for &[u8] {
224    fn as_body(&mut self) -> SendBody {
225        BodyInner::ByteSlice(self).into()
226    }
227}
228
229impl Private for &str {}
230impl AsSendBody for &str {
231    fn as_body(&mut self) -> SendBody {
232        BodyInner::ByteSlice((*self).as_ref()).into()
233    }
234}
235
236impl Private for String {}
237impl AsSendBody for String {
238    fn as_body(&mut self) -> SendBody {
239        BodyInner::ByteSlice((*self).as_ref()).into()
240    }
241}
242
243impl Private for Vec<u8> {}
244impl AsSendBody for Vec<u8> {
245    fn as_body(&mut self) -> SendBody {
246        BodyInner::ByteSlice((*self).as_ref()).into()
247    }
248}
249
250impl Private for &String {}
251impl AsSendBody for &String {
252    fn as_body(&mut self) -> SendBody {
253        BodyInner::ByteSlice((*self).as_ref()).into()
254    }
255}
256
257impl Private for &Vec<u8> {}
258impl AsSendBody for &Vec<u8> {
259    fn as_body(&mut self) -> SendBody {
260        BodyInner::ByteSlice((*self).as_ref()).into()
261    }
262}
263
264impl Private for &File {}
265impl AsSendBody for &File {
266    fn as_body(&mut self) -> SendBody {
267        BodyInner::Reader(self).into()
268    }
269}
270
271impl Private for &TcpStream {}
272impl AsSendBody for &TcpStream {
273    fn as_body(&mut self) -> SendBody {
274        BodyInner::Reader(self).into()
275    }
276}
277
278impl Private for File {}
279impl AsSendBody for File {
280    fn as_body(&mut self) -> SendBody {
281        BodyInner::Reader(self).into()
282    }
283}
284
285impl Private for TcpStream {}
286impl AsSendBody for TcpStream {
287    fn as_body(&mut self) -> SendBody {
288        BodyInner::Reader(self).into()
289    }
290}
291
292impl Private for Stdin {}
293impl AsSendBody for Stdin {
294    fn as_body(&mut self) -> SendBody {
295        BodyInner::Reader(self).into()
296    }
297}
298
299// MSRV 1.78
300// impl_into_body!(&Stdin, Reader);
301
302#[cfg(target_family = "unix")]
303use std::os::unix::net::UnixStream;
304
305#[cfg(target_family = "unix")]
306impl Private for UnixStream {}
307#[cfg(target_family = "unix")]
308impl AsSendBody for UnixStream {
309    fn as_body(&mut self) -> SendBody {
310        BodyInner::Reader(self).into()
311    }
312}
313
314impl<'a> From<BodyInner<'a>> for SendBody<'a> {
315    fn from(inner: BodyInner<'a>) -> Self {
316        SendBody {
317            inner,
318            ended: false,
319        }
320    }
321}
322
323impl Private for Body {}
324impl AsSendBody for Body {
325    fn as_body(&mut self) -> SendBody {
326        BodyInner::Body(self.as_reader()).into()
327    }
328}
329
330impl Private for Response<Body> {}
331impl AsSendBody for Response<Body> {
332    fn as_body(&mut self) -> SendBody {
333        BodyInner::Body(self.body_mut().as_reader()).into()
334    }
335}
336
337impl<const N: usize> Private for &[u8; N] {}
338impl<const N: usize> AsSendBody for &[u8; N] {
339    fn as_body(&mut self) -> SendBody {
340        BodyInner::ByteSlice(self.as_slice()).into()
341    }
342}
343
344impl Private for () {}
345impl AsSendBody for () {
346    fn as_body(&mut self) -> SendBody {
347        BodyInner::None.into()
348    }
349}