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 | |
16 | mod collect; |
17 | mod empty; |
18 | mod full; |
19 | mod limited; |
20 | mod next; |
21 | mod size_hint; |
22 | |
23 | pub mod combinators; |
24 | |
25 | pub use self::collect::Collected; |
26 | pub use self::empty::Empty; |
27 | pub use self::full::Full; |
28 | pub use self::limited::{LengthLimitError, Limited}; |
29 | pub use self::next::{Data, Trailers}; |
30 | pub use self::size_hint::SizeHint; |
31 | |
32 | use self::combinators::{BoxBody, MapData, MapErr, UnsyncBoxBody}; |
33 | use bytes::{Buf, Bytes}; |
34 | use http::HeaderMap; |
35 | use std::convert::Infallible; |
36 | use std::ops; |
37 | use std::pin::Pin; |
38 | use 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 | /// |
48 | pub 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 | |
149 | impl<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 | |
176 | impl<P> Body for Pin<P> |
177 | where |
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 | |
207 | impl<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 | |
234 | impl<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 | |
267 | impl<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 | |
300 | impl 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)] |
333 | fn _assert_bounds() { |
334 | fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {} |
335 | } |
336 | |