http_body_reader/
body_reader.rs1use std::string::FromUtf8Error;
2
3use bytes::{Buf, Bytes};
4use http::HeaderMap;
5use http_body::Body;
6use http_body_util::BodyExt;
7
8#[derive(Debug, Clone)]
12pub struct BodyReader<B> {
13 body: B,
14 #[allow(dead_code)]
15 headers: HeaderMap,
16}
17
18#[derive(Debug)]
20pub enum BodyReaderError<E, D> {
21 Read(E),
23 Decode(D),
25}
26
27impl<E, D> std::fmt::Display for BodyReaderError<E, D>
28where
29 E: std::fmt::Display,
30 D: std::fmt::Display,
31{
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 BodyReaderError::Read(err) => err.fmt(f),
35 BodyReaderError::Decode(err) => err.fmt(f),
36 }
37 }
38}
39
40impl<E, D> std::error::Error for BodyReaderError<E, D>
43where
44 E: std::fmt::Debug + std::fmt::Display,
45 D: std::fmt::Debug + std::fmt::Display,
46{
47}
48
49impl<B> BodyReader<B> {
50 #[doc = include_str!("../examples/read_bytes.rs")]
56 pub async fn bytes(self) -> Result<Bytes, B::Error>
58 where
59 B: Body,
60 B::Data: Buf,
61 {
62 let body_bytes = self.body.collect().await?.to_bytes();
63 Ok(body_bytes)
64 }
65
66 #[doc = include_str!("../examples/read_utf8.rs")]
81 pub async fn utf8(self) -> Result<String, BodyReaderError<B::Error, FromUtf8Error>>
83 where
84 B: Body,
85 B::Data: Buf,
86 {
87 let bytes = self.bytes().await.map_err(BodyReaderError::Read)?;
88 String::from_utf8(bytes.into()).map_err(BodyReaderError::Decode)
89 }
90
91 #[doc = include_str!("../examples/read_json.rs")]
102 #[cfg(feature = "json")]
104 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
105 pub async fn json<T>(self) -> Result<T, BodyReaderError<B::Error, serde_json::Error>>
106 where
107 T: serde::de::DeserializeOwned,
108 B: Body,
109 B::Data: Buf,
110 {
111 let bytes = self.bytes().await.map_err(BodyReaderError::Read)?;
112 serde_json::from_slice(&bytes).map_err(BodyReaderError::Decode)
113 }
114
115 #[doc = include_str!("../examples/read_form.rs")]
126 #[cfg(feature = "form")]
128 #[cfg_attr(docsrs, doc(cfg(feature = "form")))]
129 pub async fn form<T>(self) -> Result<T, BodyReaderError<B::Error, serde_urlencoded::de::Error>>
130 where
131 T: serde::de::DeserializeOwned,
132 B: Body,
133 B::Data: Buf,
134 {
135 let bytes = self.bytes().await.map_err(BodyReaderError::Read)?;
136 serde_urlencoded::from_bytes(&bytes).map_err(BodyReaderError::Decode)
137 }
138
139 #[doc = include_str!("../examples/map_body.rs")]
145 pub fn map<F, T>(self, f: F) -> BodyReader<T>
147 where
148 F: FnOnce(B) -> T,
149 T: Body,
150 T::Data: Buf,
151 {
152 BodyReader {
153 body: f(self.body),
154 headers: self.headers,
155 }
156 }
157}
158
159impl<B> From<http::Response<B>> for BodyReader<B> {
160 fn from(response: http::Response<B>) -> Self {
161 let (parts, body) = response.into_parts();
162 Self {
163 body,
164 headers: parts.headers,
165 }
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::BodyReaderError;
172
173 type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
174
175 #[test]
177 fn test_body_reader_error_into_boxed() {
178 let read_error = std::io::Error::new(std::io::ErrorKind::Other, "read error");
180 let error: BodyReaderError<std::io::Error, BoxError> = BodyReaderError::Read(read_error);
181 let boxed_error: BoxError = Box::new(error);
182
183 assert_eq!(boxed_error.to_string(), "read error");
184 let decode_error = std::io::Error::new(std::io::ErrorKind::Other, "decode error");
186 let error: BodyReaderError<BoxError, std::io::Error> =
187 BodyReaderError::Decode(decode_error);
188 let boxed_error: BoxError = Box::new(error);
189
190 assert_eq!(boxed_error.to_string(), "decode error");
191 }
192}