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