http_body/
lib.rs

1#![doc(html_root_url = "https://docs.rs/http-body/0.4.6")]
2#![deny(
3    missing_debug_implementations,
4    missing_docs,
5    unreachable_pub,
6    broken_intra_doc_links
7)]
8#![cfg_attr(test, deny(warnings))]
9
10//! Asynchronous HTTP request or response body.
11//!
12//! See [`Body`] for more details.
13//!
14//! [`Body`]: trait.Body.html
15
16mod collect;
17mod empty;
18mod full;
19mod limited;
20mod next;
21mod size_hint;
22
23pub mod combinators;
24
25pub use self::collect::Collected;
26pub use self::empty::Empty;
27pub use self::full::Full;
28pub use self::limited::{LengthLimitError, Limited};
29pub use self::next::{Data, Trailers};
30pub use self::size_hint::SizeHint;
31
32use self::combinators::{BoxBody, MapData, MapErr, UnsyncBoxBody};
33use bytes::{Buf, Bytes};
34use http::HeaderMap;
35use std::convert::Infallible;
36use std::ops;
37use std::pin::Pin;
38use std::task::{Context, Poll};
39
40/// Trait representing a streaming body of a Request or Response.
41///
42/// Data is streamed via the `poll_data` function, which asynchronously yields `T: Buf` values. The
43/// `size_hint` function provides insight into the total number of bytes that will be streamed.
44///
45/// The `poll_trailers` function returns an optional set of trailers used to finalize the request /
46/// response exchange. This is mostly used when using the HTTP/2.0 protocol.
47///
48pub trait Body {
49    /// Values yielded by the `Body`.
50    type Data: Buf;
51
52    /// The error type this `Body` might generate.
53    type Error;
54
55    /// Attempt to pull out the next data buffer of this stream.
56    fn poll_data(
57        self: Pin<&mut Self>,
58        cx: &mut Context<'_>,
59    ) -> Poll<Option<Result<Self::Data, Self::Error>>>;
60
61    /// Poll for an optional **single** `HeaderMap` of trailers.
62    ///
63    /// This function should only be called once `poll_data` returns `None`.
64    fn poll_trailers(
65        self: Pin<&mut Self>,
66        cx: &mut Context<'_>,
67    ) -> Poll<Result<Option<HeaderMap>, Self::Error>>;
68
69    /// Returns `true` when the end of stream has been reached.
70    ///
71    /// An end of stream means that both `poll_data` and `poll_trailers` will
72    /// return `None`.
73    ///
74    /// A return value of `false` **does not** guarantee that a value will be
75    /// returned from `poll_stream` or `poll_trailers`.
76    fn is_end_stream(&self) -> bool {
77        false
78    }
79
80    /// Returns the bounds on the remaining length of the stream.
81    ///
82    /// When the **exact** remaining length of the stream is known, the upper bound will be set and
83    /// will equal the lower bound.
84    fn size_hint(&self) -> SizeHint {
85        SizeHint::default()
86    }
87
88    /// Returns future that resolves to next data chunk, if any.
89    fn data(&mut self) -> Data<'_, Self>
90    where
91        Self: Unpin + Sized,
92    {
93        Data(self)
94    }
95
96    /// Returns future that resolves to trailers, if any.
97    fn trailers(&mut self) -> Trailers<'_, Self>
98    where
99        Self: Unpin + Sized,
100    {
101        Trailers(self)
102    }
103
104    /// Maps this body's data value to a different value.
105    fn map_data<F, B>(self, f: F) -> MapData<Self, F>
106    where
107        Self: Sized,
108        F: FnMut(Self::Data) -> B,
109        B: Buf,
110    {
111        MapData::new(self, f)
112    }
113
114    /// Maps this body's error value to a different value.
115    fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
116    where
117        Self: Sized,
118        F: FnMut(Self::Error) -> E,
119    {
120        MapErr::new(self, f)
121    }
122
123    /// Turn this body into [`Collected`] body which will collect all the DATA frames
124    /// and trailers.
125    fn collect(self) -> crate::collect::Collect<Self>
126    where
127        Self: Sized,
128    {
129        collect::Collect::new(self)
130    }
131
132    /// Turn this body into a boxed trait object.
133    fn boxed(self) -> BoxBody<Self::Data, Self::Error>
134    where
135        Self: Sized + Send + Sync + 'static,
136    {
137        BoxBody::new(self)
138    }
139
140    /// Turn this body into a boxed trait object that is !Sync.
141    fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
142    where
143        Self: Sized + Send + 'static,
144    {
145        UnsyncBoxBody::new(self)
146    }
147}
148
149impl<T: Body + Unpin + ?Sized> Body for &mut T {
150    type Data = T::Data;
151    type Error = T::Error;
152
153    fn poll_data(
154        mut self: Pin<&mut Self>,
155        cx: &mut Context<'_>,
156    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
157        Pin::new(&mut **self).poll_data(cx)
158    }
159
160    fn poll_trailers(
161        mut self: Pin<&mut Self>,
162        cx: &mut Context<'_>,
163    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
164        Pin::new(&mut **self).poll_trailers(cx)
165    }
166
167    fn is_end_stream(&self) -> bool {
168        Pin::new(&**self).is_end_stream()
169    }
170
171    fn size_hint(&self) -> SizeHint {
172        Pin::new(&**self).size_hint()
173    }
174}
175
176impl<P> Body for Pin<P>
177where
178    P: Unpin + ops::DerefMut,
179    P::Target: Body,
180{
181    type Data = <<P as ops::Deref>::Target as Body>::Data;
182    type Error = <<P as ops::Deref>::Target as Body>::Error;
183
184    fn poll_data(
185        self: Pin<&mut Self>,
186        cx: &mut Context<'_>,
187    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
188        Pin::get_mut(self).as_mut().poll_data(cx)
189    }
190
191    fn poll_trailers(
192        self: Pin<&mut Self>,
193        cx: &mut Context<'_>,
194    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
195        Pin::get_mut(self).as_mut().poll_trailers(cx)
196    }
197
198    fn is_end_stream(&self) -> bool {
199        self.as_ref().is_end_stream()
200    }
201
202    fn size_hint(&self) -> SizeHint {
203        self.as_ref().size_hint()
204    }
205}
206
207impl<T: Body + Unpin + ?Sized> Body for Box<T> {
208    type Data = T::Data;
209    type Error = T::Error;
210
211    fn poll_data(
212        mut self: Pin<&mut Self>,
213        cx: &mut Context<'_>,
214    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
215        Pin::new(&mut **self).poll_data(cx)
216    }
217
218    fn poll_trailers(
219        mut self: Pin<&mut Self>,
220        cx: &mut Context<'_>,
221    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
222        Pin::new(&mut **self).poll_trailers(cx)
223    }
224
225    fn is_end_stream(&self) -> bool {
226        self.as_ref().is_end_stream()
227    }
228
229    fn size_hint(&self) -> SizeHint {
230        self.as_ref().size_hint()
231    }
232}
233
234impl<B: Body> Body for http::Request<B> {
235    type Data = B::Data;
236    type Error = B::Error;
237
238    fn poll_data(
239        self: Pin<&mut Self>,
240        cx: &mut Context<'_>,
241    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
242        unsafe {
243            self.map_unchecked_mut(http::Request::body_mut)
244                .poll_data(cx)
245        }
246    }
247
248    fn poll_trailers(
249        self: Pin<&mut Self>,
250        cx: &mut Context<'_>,
251    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
252        unsafe {
253            self.map_unchecked_mut(http::Request::body_mut)
254                .poll_trailers(cx)
255        }
256    }
257
258    fn is_end_stream(&self) -> bool {
259        self.body().is_end_stream()
260    }
261
262    fn size_hint(&self) -> SizeHint {
263        self.body().size_hint()
264    }
265}
266
267impl<B: Body> Body for http::Response<B> {
268    type Data = B::Data;
269    type Error = B::Error;
270
271    fn poll_data(
272        self: Pin<&mut Self>,
273        cx: &mut Context<'_>,
274    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
275        unsafe {
276            self.map_unchecked_mut(http::Response::body_mut)
277                .poll_data(cx)
278        }
279    }
280
281    fn poll_trailers(
282        self: Pin<&mut Self>,
283        cx: &mut Context<'_>,
284    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
285        unsafe {
286            self.map_unchecked_mut(http::Response::body_mut)
287                .poll_trailers(cx)
288        }
289    }
290
291    fn is_end_stream(&self) -> bool {
292        self.body().is_end_stream()
293    }
294
295    fn size_hint(&self) -> SizeHint {
296        self.body().size_hint()
297    }
298}
299
300impl Body for String {
301    type Data = Bytes;
302    type Error = Infallible;
303
304    fn poll_data(
305        mut self: Pin<&mut Self>,
306        _cx: &mut Context<'_>,
307    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
308        if !self.is_empty() {
309            let s = std::mem::take(&mut *self);
310            Poll::Ready(Some(Ok(s.into_bytes().into())))
311        } else {
312            Poll::Ready(None)
313        }
314    }
315
316    fn poll_trailers(
317        self: Pin<&mut Self>,
318        _cx: &mut Context<'_>,
319    ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
320        Poll::Ready(Ok(None))
321    }
322
323    fn is_end_stream(&self) -> bool {
324        self.is_empty()
325    }
326
327    fn size_hint(&self) -> SizeHint {
328        SizeHint::with_exact(self.len() as u64)
329    }
330}
331
332#[cfg(test)]
333fn _assert_bounds() {
334    fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {}
335}