|
1 | 1 | //! HTTP specific body utilities.
|
2 |
| -//! |
3 |
| -//! This module contains traits and helper types to work with http bodies. Most |
4 |
| -//! of the types in this module are based around [`http_body::Body`]. |
5 | 2 |
|
6 |
| -use crate::{Error, Status}; |
7 |
| -use bytes::{Buf, Bytes}; |
8 |
| -use http_body::Body as HttpBody; |
9 |
| -use std::{ |
10 |
| - fmt, |
11 |
| - pin::Pin, |
12 |
| - task::{Context, Poll}, |
13 |
| -}; |
| 3 | +use crate::Status; |
| 4 | +use bytes::Bytes; |
| 5 | +use http_body::{Body, Empty}; |
14 | 6 |
|
15 |
| -/// A trait alias for [`http_body::Body`]. |
16 |
| -pub trait Body: sealed::Sealed + Send + Sync { |
17 |
| - /// The body data type. |
18 |
| - type Data: Buf; |
19 |
| - /// The errors produced from the body. |
20 |
| - type Error: Into<Error>; |
| 7 | +/// A type erased HTTP body used for tonic services. |
| 8 | +pub type BoxBody = http_body::combinators::BoxBody<Bytes, Status>; |
21 | 9 |
|
22 |
| - /// Check if the stream is over or not. |
23 |
| - /// |
24 |
| - /// Reference [`http_body::Body::is_end_stream`]. |
25 |
| - fn is_end_stream(&self) -> bool; |
26 |
| - |
27 |
| - /// Poll for more data from the body. |
28 |
| - /// |
29 |
| - /// Reference [`http_body::Body::poll_data`]. |
30 |
| - fn poll_data( |
31 |
| - self: Pin<&mut Self>, |
32 |
| - cx: &mut Context<'_>, |
33 |
| - ) -> Poll<Option<Result<Self::Data, Self::Error>>>; |
34 |
| - |
35 |
| - /// Poll for the trailing headers. |
36 |
| - /// |
37 |
| - /// Reference [`http_body::Body::poll_trailers`]. |
38 |
| - fn poll_trailers( |
39 |
| - self: Pin<&mut Self>, |
40 |
| - cx: &mut Context<'_>, |
41 |
| - ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>>; |
42 |
| -} |
43 |
| - |
44 |
| -impl<T> Body for T |
45 |
| -where |
46 |
| - T: HttpBody + Send + Sync + 'static, |
47 |
| - T::Error: Into<Error>, |
48 |
| -{ |
49 |
| - type Data = T::Data; |
50 |
| - type Error = T::Error; |
51 |
| - |
52 |
| - fn is_end_stream(&self) -> bool { |
53 |
| - HttpBody::is_end_stream(self) |
54 |
| - } |
55 |
| - |
56 |
| - fn poll_data( |
57 |
| - self: Pin<&mut Self>, |
58 |
| - cx: &mut Context<'_>, |
59 |
| - ) -> Poll<Option<Result<Self::Data, Self::Error>>> { |
60 |
| - HttpBody::poll_data(self, cx) |
61 |
| - } |
62 |
| - |
63 |
| - fn poll_trailers( |
64 |
| - self: Pin<&mut Self>, |
65 |
| - cx: &mut Context<'_>, |
66 |
| - ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { |
67 |
| - HttpBody::poll_trailers(self, cx) |
68 |
| - } |
69 |
| -} |
70 |
| - |
71 |
| -impl<T> sealed::Sealed for T |
72 |
| -where |
73 |
| - T: HttpBody, |
74 |
| - T::Error: Into<Error>, |
75 |
| -{ |
76 |
| -} |
77 |
| - |
78 |
| -mod sealed { |
79 |
| - pub trait Sealed {} |
80 |
| -} |
81 |
| - |
82 |
| -/// A type erased http body. |
83 |
| -pub struct BoxBody { |
84 |
| - inner: Pin<Box<dyn Body<Data = Bytes, Error = Status> + Send + Sync + 'static>>, |
85 |
| -} |
86 |
| - |
87 |
| -struct MapBody<B>(B); |
88 |
| - |
89 |
| -impl BoxBody { |
90 |
| - /// Create a new `BoxBody` mapping item and error to the default types. |
91 |
| - pub fn new<B>(inner: B) -> Self |
92 |
| - where |
93 |
| - B: Body<Data = Bytes, Error = Status> + Send + Sync + 'static, |
94 |
| - { |
95 |
| - BoxBody { |
96 |
| - inner: Box::pin(inner), |
97 |
| - } |
98 |
| - } |
99 |
| - |
100 |
| - /// Create a new `BoxBody` mapping item and error to the default types. |
101 |
| - pub fn map_from<B>(inner: B) -> Self |
102 |
| - where |
103 |
| - B: Body + Send + Sync + 'static, |
104 |
| - B::Error: Into<crate::Error>, |
105 |
| - { |
106 |
| - BoxBody { |
107 |
| - inner: Box::pin(MapBody(inner)), |
108 |
| - } |
109 |
| - } |
110 |
| - |
111 |
| - /// Create a new `BoxBody` that is empty. |
112 |
| - pub fn empty() -> Self { |
113 |
| - BoxBody { |
114 |
| - inner: Box::pin(EmptyBody::default()), |
115 |
| - } |
116 |
| - } |
117 |
| -} |
118 |
| - |
119 |
| -impl HttpBody for BoxBody { |
120 |
| - type Data = Bytes; |
121 |
| - type Error = Status; |
122 |
| - |
123 |
| - fn is_end_stream(&self) -> bool { |
124 |
| - self.inner.is_end_stream() |
125 |
| - } |
126 |
| - |
127 |
| - fn poll_data( |
128 |
| - mut self: Pin<&mut Self>, |
129 |
| - cx: &mut Context<'_>, |
130 |
| - ) -> Poll<Option<Result<Self::Data, Self::Error>>> { |
131 |
| - Body::poll_data(self.inner.as_mut(), cx) |
132 |
| - } |
133 |
| - |
134 |
| - fn poll_trailers( |
135 |
| - mut self: Pin<&mut Self>, |
136 |
| - cx: &mut Context<'_>, |
137 |
| - ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { |
138 |
| - Body::poll_trailers(self.inner.as_mut(), cx) |
139 |
| - } |
140 |
| -} |
141 |
| - |
142 |
| -impl<B> HttpBody for MapBody<B> |
143 |
| -where |
144 |
| - B: Body, |
145 |
| - B::Error: Into<crate::Error>, |
146 |
| -{ |
147 |
| - type Data = Bytes; |
148 |
| - type Error = Status; |
149 |
| - |
150 |
| - fn is_end_stream(&self) -> bool { |
151 |
| - self.0.is_end_stream() |
152 |
| - } |
153 |
| - |
154 |
| - fn poll_data( |
155 |
| - self: Pin<&mut Self>, |
156 |
| - cx: &mut Context<'_>, |
157 |
| - ) -> Poll<Option<Result<Self::Data, Self::Error>>> { |
158 |
| - let v = unsafe { |
159 |
| - let me = self.get_unchecked_mut(); |
160 |
| - Pin::new_unchecked(&mut me.0).poll_data(cx) |
161 |
| - }; |
162 |
| - match futures_util::ready!(v) { |
163 |
| - Some(Ok(mut i)) => Poll::Ready(Some(Ok(i.copy_to_bytes(i.remaining())))), |
164 |
| - Some(Err(e)) => { |
165 |
| - let err = Status::map_error(e.into()); |
166 |
| - Poll::Ready(Some(Err(err))) |
167 |
| - } |
168 |
| - None => Poll::Ready(None), |
169 |
| - } |
170 |
| - } |
171 |
| - |
172 |
| - fn poll_trailers( |
173 |
| - self: Pin<&mut Self>, |
174 |
| - cx: &mut Context<'_>, |
175 |
| - ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { |
176 |
| - let v = unsafe { |
177 |
| - let me = self.get_unchecked_mut(); |
178 |
| - Pin::new_unchecked(&mut me.0).poll_trailers(cx) |
179 |
| - }; |
180 |
| - |
181 |
| - let v = futures_util::ready!(v).map_err(|e| Status::from_error(&*e.into())); |
182 |
| - Poll::Ready(v) |
183 |
| - } |
184 |
| -} |
185 |
| - |
186 |
| -impl fmt::Debug for BoxBody { |
187 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
188 |
| - f.debug_struct("BoxBody").finish() |
189 |
| - } |
190 |
| -} |
191 |
| - |
192 |
| -#[derive(Debug, Default)] |
193 |
| -struct EmptyBody { |
194 |
| - _p: (), |
195 |
| -} |
196 |
| - |
197 |
| -impl HttpBody for EmptyBody { |
198 |
| - type Data = Bytes; |
199 |
| - type Error = Status; |
200 |
| - |
201 |
| - fn is_end_stream(&self) -> bool { |
202 |
| - true |
203 |
| - } |
204 |
| - |
205 |
| - fn poll_data( |
206 |
| - self: Pin<&mut Self>, |
207 |
| - _cx: &mut Context<'_>, |
208 |
| - ) -> Poll<Option<Result<Self::Data, Self::Error>>> { |
209 |
| - Poll::Ready(None) |
210 |
| - } |
211 |
| - |
212 |
| - fn poll_trailers( |
213 |
| - self: Pin<&mut Self>, |
214 |
| - _cx: &mut Context<'_>, |
215 |
| - ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { |
216 |
| - Poll::Ready(Ok(None)) |
217 |
| - } |
| 10 | +pub(crate) fn empty() -> BoxBody { |
| 11 | + Empty::new().map_err(|err| match err {}).boxed() |
218 | 12 | }
|
0 commit comments