1use super::{super::pieces::*, reader::*};
2
3use {
4 bytes::*,
5 http::*,
6 http_body::*,
7 kutil_io::reader::*,
8 kutil_std::error::*,
9 std::{io, result::Result, string::*},
10 thiserror::*,
11 tokio::io::*,
12};
13
14#[allow(async_fn_in_trait)]
22pub trait ReadBodyIntoBytes: Sized {
23 async fn read_into_bytes_or_pieces(
33 self,
34 declared_size: Option<usize>,
35 min_size: usize,
36 max_size: usize,
37 ) -> Result<(Bytes, Vec<HeaderMap>), ErrorWithBodyPieces<ReadBodyError, Self>>;
38
39 async fn read_into_bytes(self, max_size: usize) -> Result<(Bytes, Vec<HeaderMap>), ReadBodyError> {
44 self.read_into_bytes_or_pieces(None, 0, max_size).await.map_err(|error| error.error)
45 }
46
47 async fn read_into_string_or_pieces(
51 self,
52 declared_size: Option<usize>,
53 min_size: usize,
54 max_size: usize,
55 ) -> Result<(String, Vec<HeaderMap>), ErrorWithBodyPieces<ReadBodyError, Self>> {
56 let (bytes, trailers) = self.read_into_bytes_or_pieces(declared_size, min_size, max_size).await?;
57 let string =
58 String::from_utf8(bytes.to_vec()).map_err(|error| ErrorWithBodyPieces::from(ReadBodyError::from(error)))?;
59 Ok((string, trailers))
60 }
61
62 async fn read_into_string(self, max_size: usize) -> Result<(String, Vec<HeaderMap>), ReadBodyError> {
67 self.read_into_string_or_pieces(None, 0, max_size).await.map_err(|error| error.error)
68 }
69}
70
71impl<BodyT> ReadBodyIntoBytes for BodyT
72where
73 BodyT: Body + Unpin,
74 BodyT::Error: Into<CapturedError>,
75{
76 async fn read_into_bytes_or_pieces(
77 self,
78 declared_size: Option<usize>,
79 min_size: usize,
80 max_size: usize,
81 ) -> Result<(Bytes, Vec<HeaderMap>), ErrorWithBodyPieces<ReadBodyError, Self>> {
82 assert!(max_size >= min_size);
83
84 let read_size = match declared_size {
85 Some(declared_size) => {
86 assert!(declared_size >= min_size);
87 assert!(declared_size <= max_size);
88 declared_size
89 }
90
91 None => max_size,
92 };
93
94 let reader = self.into_reader();
95
96 let mut bytes = BytesMut::with_capacity(read_size);
97 let (mut reader, _size) = read_at_most(reader, &mut bytes, read_size as u64)
98 .await
99 .map_err(|error| ErrorWithBodyPieces::from(ReadBodyError::from(error)))?;
100
101 match reader.read_u8().await {
103 Ok(byte) => {
104 println!("!!!!!!!!!!!!!!!!! {:?} {}", read_size, bytes.len());
105 let (body, remainder, _trailers) = reader.into_inner();
106
107 bytes.put_u8(byte);
109 bytes.put(remainder);
110
111 return Err(ErrorWithBodyPieces::new(
112 io::Error::new(io::ErrorKind::FileTooLarge, format!("body is bigger than {}", read_size)).into(),
113 Some(BodyPieces::new(body, bytes.into())),
114 ));
115 }
116
117 Err(error) => {
118 if error.kind() != io::ErrorKind::UnexpectedEof {
120 let (body, remainder, _trailers) = reader.into_inner();
121 bytes.put(remainder); return Err(ErrorWithBodyPieces::new(error.into(), Some(BodyPieces::new(body, bytes.into()))));
123 }
124 }
125 }
126
127 let fulfilled_size = bytes.len();
128
129 if let Some(declared_size) = declared_size {
130 if declared_size != fulfilled_size {
131 tracing::warn!("declared size is {} but actual body size is {}", declared_size, fulfilled_size);
133 }
134 }
135
136 if fulfilled_size < min_size {
137 let (body, remainder, _trailers) = reader.into_inner();
138 bytes.put(remainder); return Err(ErrorWithBodyPieces::new(
140 io::Error::new(
141 io::ErrorKind::FileTooLarge,
142 format!("body is too big: {} > {}", fulfilled_size, min_size),
143 )
144 .into(),
145 Some(BodyPieces::new(body, bytes.into())),
146 ));
147 }
148
149 let (_body, remainder, trailers) = reader.into_inner();
150 bytes.put(remainder); Ok((bytes.into(), trailers))
152 }
153}
154
155#[derive(Debug, Error)]
161pub enum ReadBodyError {
162 #[error("I/O: {0}")]
164 IO(#[from] io::Error),
165
166 #[error("UTF8: {0}")]
168 UTF8(#[from] FromUtf8Error),
169}