generic_async_http_client/
response.rs

1use crate::{imp, Error, HeaderName, HeaderValue};
2use serde::de::DeserializeOwned;
3use std::convert::TryInto;
4
5/// The response of a webserver.
6/// Headers and Status are available from the start,
7/// the body must be polled/awaited again
8///
9/// Depending on the chosen implementation, `Response` implements `Into<http_types::Response>` or `Into<hyper::Response>`.
10pub struct Response(pub(crate) imp::Resp);
11impl Response {
12    /// Return the status code
13    pub fn status_code(&self) -> u16 {
14        self.0.status()
15    }
16    /// Return the status as string
17    pub fn status(&self) -> &str {
18        self.0.status_str()
19    }
20    /// Return the Body as some type deserialized from JSON
21    pub async fn json<D: DeserializeOwned>(&mut self) -> Result<D, Error> {
22        Ok(self.0.json().await?)
23    }
24    /// Return the whole Body as Bytes
25    pub async fn content(&mut self) -> Result<Vec<u8>, Error> {
26        Ok(self.0.bytes().await?)
27    }
28    /// Return the whole Body as String
29    pub async fn text(&mut self) -> Result<String, Error> {
30        Ok(self.0.string().await?)
31    }
32    /// If there are multiple values associated with the key, then the first one is returned.
33    pub fn header(
34        &self,
35        name: impl TryInto<HeaderName, Error = imp::Error>,
36    ) -> Option<&HeaderValue> {
37        match name.try_into() {
38            Err(_) => None,
39            Ok(name) => self.0.get_header(name.into()).map(|v| v.into()),
40        }
41    }
42    /// return an error if `name` is not a valid header name
43    pub fn all_header(
44        &self,
45        name: impl TryInto<HeaderName, Error = imp::Error>,
46    ) -> Result<impl Iterator<Item = &HeaderValue>, Error> {
47        let name: HeaderName = name.try_into()?;
48        Ok(self.0.get_headers(name.into()).map(|v| v.into()))
49    }
50    /// Each key will be yielded once per associated value. So, if a key has 3 associated values, it will be yielded 3 times.
51    pub fn headers(&self) -> impl Iterator<Item = (&HeaderName, &HeaderValue)> {
52        self.0.header_iter().map(|(n, v)| (n.into(), v.into()))
53    }
54    /*
55    TODO cookie
56    TODO encoding
57    TODO raw (impl Read and or Stream)
58    */
59}
60
61impl std::fmt::Debug for Response {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        let h: Vec<(&HeaderName, &HeaderValue)> = self.headers().collect();
64        write!(f, "HTTP {} Header: {:?}", self.status_code(), h)
65    }
66}
67
68pub trait Responses {
69    fn status(&self) -> u16;
70    fn status_str(&self) -> &'static str;
71    async fn json<D: DeserializeOwned>(&mut self) -> Result<D, imp::Error>;
72    async fn bytes(&mut self) -> Result<Vec<u8>, imp::Error>;
73    async fn string(&mut self) -> Result<String, imp::Error>;
74    fn get_header(&self, name: imp::HeaderName) -> Option<&imp::HeaderValue>;
75    fn get_headers(&self, name: imp::HeaderName) -> impl Iterator<Item = &imp::HeaderValue>;
76    fn header_iter(&self) -> impl Iterator<Item = (&imp::HeaderName, &imp::HeaderValue)>;
77}