simple_hyper_client/blocking/
body.rs1use super::client::KeepClientAlive;
8
9use futures_util::StreamExt;
10use http_body_util::BodyExt;
11use hyper::body::Body as HyperBody;
12use hyper::body::{Buf, Bytes};
13use tokio::sync::mpsc;
14
15use std::future::Future;
16use std::{fmt, io};
17
18pub struct Body {
20 pub(super) keep_client_alive: KeepClientAlive,
21 bytes: Bytes,
22 rx: mpsc::Receiver<io::Result<Bytes>>,
23}
24
25impl fmt::Debug for Body {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.debug_struct("Body").finish()
28 }
29}
30
31impl Body {
32 pub(super) fn new<T>(hyper_body: T) -> (impl Future<Output = ()> + Send + 'static, Self)
33 where
34 T: HyperBody + Send + 'static,
35 T::Data: Send + Into<Bytes>,
36 T::Error: std::error::Error + Send + Sync + 'static,
37 {
38 let (tx, rx) = mpsc::channel(1);
39
40 let fut = async move {
41 let mut stream = std::pin::pin!(hyper_body.into_data_stream());
42
43 loop {
44 tokio::select! {
45 _ = tx.closed() => {
46 break; }
48
49 res = stream.next() => {
50 let res = match res {
51 None => break, Some(Ok(chunk)) => {
54 let chunk = chunk.into();
55
56 if chunk.is_empty() {
57 continue;
58 } else {
59 Ok(chunk)
60 }
61 }
62
63 Some(Err(e)) => Err(io::Error::new(io::ErrorKind::Other, e)),
64 };
65
66 if tx.send(res).await.is_err() {
67 break; }
69 }
70 }
71 }
72 };
73
74 let body = Body {
75 keep_client_alive: KeepClientAlive::empty(),
76 bytes: Bytes::new(),
77 rx,
78 };
79
80 (fut, body)
81 }
82}
83
84impl io::Read for Body {
85 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
86 if self.bytes.is_empty() {
87 match self.rx.blocking_recv() {
88 Some(Ok(bytes)) => {
89 self.bytes = bytes;
90 }
91 Some(Err(e)) => return Err(e),
92 None => return Ok(0),
93 }
94 }
95 (&mut self.bytes).reader().read(buf)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use http_body_util::{Channel, Full, StreamBody};
103 use hyper::body::Frame;
104 use std::io::Read;
105 use std::{future::Future, thread};
106 use tokio::time::{self, Duration};
107
108 fn run_future<F: Future<Output = ()> + Send + 'static>(fut: F) {
109 thread::spawn(move || {
110 let rt = tokio::runtime::Builder::new_current_thread()
111 .enable_all()
112 .build()
113 .unwrap();
114 rt.block_on(fut);
115 });
116 }
117
118 #[test]
119 fn single_chunk() {
120 let body = Full::new(&b"hello, world!"[..]);
121 let (fut, mut reader) = Body::new(body);
122 run_future(fut);
123
124 let mut bytes = Vec::<u8>::new();
125 reader.read_to_end(&mut bytes).unwrap();
126 assert_eq!(bytes, b"hello, world!");
127 }
128
129 #[test]
130 fn multiple_chunks() {
131 let (mut sender, body) = Channel::<&[u8]>::new(5);
132 let (fut, mut reader) = Body::new(body);
133
134 run_future(async move {
135 let h = tokio::spawn(fut);
136
137 sender.send_data(b"hello").await.unwrap();
138 time::sleep(Duration::from_millis(10)).await;
139 sender.send_data(b", ").await.unwrap();
140 sender.send_data(b"world!").await.unwrap();
141
142 drop(sender);
143 h.await.unwrap();
144 });
145
146 let mut bytes = Vec::<u8>::new();
147 reader.read_to_end(&mut bytes).unwrap();
148 assert_eq!(bytes, b"hello, world!");
149 }
150
151 #[test]
152 fn with_empty_chunk() {
153 let (mut sender, body) = Channel::<&[u8]>::new(5);
154 let (fut, mut reader) = Body::new(body);
155
156 run_future(async move {
157 let h = tokio::spawn(fut);
158
159 sender.send_data(b"hello").await.unwrap();
160 time::sleep(Duration::from_millis(10)).await;
161 sender.send_data(b"").await.unwrap();
162 sender.send_data(b", world!").await.unwrap();
163
164 drop(sender);
165 h.await.unwrap();
166 });
167
168 let mut bytes = Vec::<u8>::new();
169 reader.read_to_end(&mut bytes).unwrap();
170 assert_eq!(bytes, b"hello, world!");
171 }
172
173 #[test]
174 fn hyper_error() {
175 eprintln!("test");
176 let chunks: Vec<Result<&[u8], io::Error>> = vec![
177 Ok(b"hello"),
178 Ok(b" "),
179 Ok(b"world"),
180 Err(io::ErrorKind::BrokenPipe.into()),
181 ];
182 let chunks = chunks.into_iter().map(|res| res.map(Frame::data));
183 let stream = futures_util::stream::iter(chunks);
184 let body = StreamBody::new(stream);
185 let (fut, mut reader) = Body::new(body);
186
187 run_future(fut);
188
189 let mut bytes = Vec::<u8>::new();
190 let err = reader.read_to_end(&mut bytes).unwrap_err();
191 assert_eq!(err.kind(), io::ErrorKind::Other);
192 assert_eq!(bytes, b"hello world");
193
194 let mut buf = [0u8; 8];
195 let n = reader.read(&mut buf).unwrap();
196 assert_eq!(n, 0);
197 }
198}