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}