simple_request/
response.rs

1use std::io;
2
3use hyper::{
4  StatusCode,
5  header::{HeaderValue, HeaderMap},
6  body::Incoming,
7};
8use http_body_util::BodyExt;
9
10use futures_util::{Stream, StreamExt};
11
12use crate::{Client, Error};
13
14// Borrows the client so its async task lives as long as this response exists.
15#[allow(dead_code)]
16#[derive(Debug)]
17pub struct Response<'a> {
18  pub(crate) response: hyper::Response<Incoming>,
19  pub(crate) size_limit: Option<usize>,
20  pub(crate) client: &'a Client,
21}
22
23impl Response<'_> {
24  pub fn status(&self) -> StatusCode {
25    self.response.status()
26  }
27  pub fn headers(&self) -> &HeaderMap<HeaderValue> {
28    self.response.headers()
29  }
30  pub async fn body(self) -> Result<impl std::io::Read, Error> {
31    let mut body = self.response.into_body().into_data_stream();
32    let mut res: Vec<u8> = vec![];
33    loop {
34      if let Some(size_limit) = self.size_limit {
35        let (lower, upper) = body.size_hint();
36        if res.len().wrapping_add(upper.unwrap_or(lower)) > size_limit.min(usize::MAX - 1) {
37          Err(Error::ConnectionError("response exceeded size limit".into()))?;
38        }
39      }
40
41      let Some(part) = body.next().await else { break };
42      let part = part.map_err(Error::Hyper)?;
43      res.extend(part.as_ref());
44    }
45    Ok(io::Cursor::new(res))
46  }
47}