flawless_http/
response.rs

1use std::string::FromUtf8Error;
2
3use base64::{prelude::BASE64_STANDARD, Engine};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Response {
7    pub(crate) status_code: u16,
8    pub(crate) url: String,
9    pub(crate) headers: Vec<(String, String)>,
10    pub(crate) body: Vec<u8>,
11}
12
13impl Response {
14    /// The status code (e.g. 200)
15    pub fn status_code(&self) -> u16 {
16        self.status_code
17    }
18
19    /// The final URL. This can differ from the request URL when redirects are followed.
20    pub fn url(&self) -> &str {
21        &self.url
22    }
23
24    /// The header value for the given name, or None if not found.
25    ///
26    /// For historical reasons, the HTTP spec allows for header values to be encoded using encodings
27    /// like iso-8859-1. Such encodings mean the values are not possible to interpret as utf-8.
28    ///
29    /// In case the header value can't be read as utf-8, this function also returns `None`.
30    pub fn header(&self, name: &str) -> Option<&str> {
31        for header in self.headers.iter() {
32            if header.0 == name {
33                return Some(&header.1);
34            }
35        }
36        None
37    }
38
39    /// Turns the response into a `utf-8` encoded `String`.
40    ///
41    /// If the encoding fails, returns an error.
42    pub fn text(self) -> Result<String, FromUtf8Error> {
43        String::from_utf8(self.body)
44    }
45
46    /// Deserializes the response into a JSON value.
47    ///
48    /// # Any type
49    ///
50    /// ```no_run
51    /// use serde_json::Value;
52    /// use flawless_http::get;
53    ///
54    /// let response = get("https://httpbin.org/get").send().unwrap();
55    /// let json: Value = response.json().unwrap();
56    ///
57    /// assert_eq!(json["url"].as_str().unwrap(), "https://httpbin.org/get");
58    /// ```
59    ///
60    /// # Specific type
61    ///
62    /// ```no_run
63    /// use std::collections::HashMap;
64    ///
65    /// use flawless_http::get;
66    ///
67    /// #[derive(serde::Deserialize)]
68    /// struct BinGet {
69    ///   args: HashMap<String, String>,
70    ///   headers: HashMap<String, String>,
71    ///   origin: String,
72    ///   url: String
73    /// }
74    ///
75    /// let response = get("https://httpbin.org/get").send().unwrap();
76    /// let json: BinGet = response.json().unwrap();
77    ///
78    /// assert_eq!(json.url, "https://httpbin.org/get");
79    /// ```
80    #[cfg(feature = "json")]
81    pub fn json<T: serde::de::DeserializeOwned>(self) -> Result<T, serde_json::Error> {
82        serde_json::from_slice(&self.body)
83    }
84
85    /// Returns the raw body of a response.
86    pub fn body(self) -> Vec<u8> {
87        self.body
88    }
89}
90
91impl From<flawless_wasabi::HttpResponse> for Response {
92    fn from(value: flawless_wasabi::HttpResponse) -> Self {
93        let body =
94            BASE64_STANDARD.decode(value.body).expect("Should always be a correctly encoded base64 value");
95        Self { status_code: value.status_code, url: value.url, headers: value.headers, body }
96    }
97}