http_request/response/response_binary/
impl.rs

1use crate::*;
2
3/// Implements the `ResponseTrait` trait for `HttpResponseBinary`.
4///
5/// This implementation specifies the associated types for binary and text representations
6/// of HTTP responses, enabling seamless conversion and handling of HTTP response data.
7///
8/// # Associated Types
9/// - `OutputText`: Specifies the text representation of an HTTP response (`HttpResponseText`).
10/// - `OutputBinary`: Specifies the binary representation of an HTTP response (`HttpResponseBinary`).
11impl ResponseTrait for HttpResponseBinary {
12    type OutputText = HttpResponseText;
13    type OutputBinary = HttpResponseBinary;
14
15    fn from(response: &[u8]) -> Self
16    where
17        Self: Sized,
18    {
19        let split_lines: Vec<&[u8]> = split_multi_byte(response, HTTP_BR_BYTES);
20        let mut lines: IntoIter<&[u8]> = split_lines.into_iter();
21        let status_line: &[u8] = lines.next().unwrap_or(&[]);
22        let status_parts: Vec<&[u8]> = split_whitespace(&status_line);
23        let http_version: HttpVersion = String::from_utf8_lossy(
24            status_parts
25                .get(0)
26                .unwrap_or(&HttpVersion::Unknown(String::new()).to_string().as_bytes()),
27        )
28        .to_string()
29        .parse::<HttpVersion>()
30        .unwrap_or_default();
31        let status_code: ResponseStatusCode = status_parts
32            .get(1)
33            .and_then(|part| std::str::from_utf8(part).ok())
34            .unwrap_or(&HttpStatus::Ok.to_string())
35            .parse()
36            .unwrap_or(HttpStatus::Unknown.code());
37        let status_text: String = status_parts.get(2..).map_or_else(
38            || HttpStatus::Unknown.to_string(),
39            |parts| String::from_utf8_lossy(&parts.concat()).to_string(),
40        );
41        let mut headers: HashMapXxHash3_64<String, String> = hash_map_xxhash3_64();
42        while let Some(line) = lines.next() {
43            if line.is_empty() {
44                break;
45            }
46            let header_parts: Vec<&[u8]> = split_multi_byte(&line, COLON_SPACE_BYTES);
47            if header_parts.len() == 2 {
48                let key: String = String::from_utf8_lossy(header_parts[0]).trim().to_string();
49                let value: String = String::from_utf8_lossy(header_parts[1]).trim().to_string();
50                headers.insert(key, value);
51            }
52        }
53        let body: Vec<u8> = lines.clone().collect::<Vec<&[u8]>>().join(BR_BYTES);
54        HttpResponseBinary {
55            http_version: Arc::new(RwLock::new(http_version)),
56            status_code,
57            status_text: Arc::new(RwLock::new(status_text)),
58            headers: Arc::new(RwLock::new(headers)),
59            body: Arc::new(RwLock::new(body)),
60        }
61    }
62
63    fn binary(&self) -> Self::OutputBinary {
64        self.clone()
65    }
66
67    fn text(&self) -> HttpResponseText {
68        let http_response: HttpResponseBinary = self.clone();
69        let body_bin: Vec<u8> = http_response
70            .body
71            .read()
72            .map_or(Vec::new(), |body| body.clone());
73        let body: String = String::from_utf8_lossy(&body_bin).to_string();
74        HttpResponseText {
75            http_version: http_response.http_version,
76            status_code: http_response.status_code,
77            status_text: http_response.status_text,
78            headers: http_response.headers,
79            body: Arc::new(RwLock::new(body)),
80        }
81    }
82
83    fn decode(&self, buffer_size: usize) -> HttpResponseBinary {
84        let http_response: HttpResponseBinary = self.clone();
85        let body: Vec<u8> = Compress::from(
86            &self
87                .headers
88                .read()
89                .map_or(hash_map_xxhash3_64(), |headers| headers.clone()),
90        )
91        .decode(
92            &self.body.read().map_or(Vec::new(), |body| body.clone()),
93            buffer_size,
94        )
95        .into_owned();
96        HttpResponseBinary {
97            http_version: http_response.http_version,
98            status_code: http_response.status_code,
99            status_text: http_response.status_text,
100            headers: http_response.headers,
101            body: Arc::new(RwLock::new(body)),
102        }
103    }
104}
105
106impl HttpResponseBinary {
107    /// Retrieves the HTTP version associated with this response.
108    ///
109    /// # Returns
110    /// - `HttpVersion`: The HTTP version (e.g., HTTP/1.1, HTTP/2, etc.) used for the response.
111    pub fn get_http_version(&self) -> HttpVersion {
112        if let Ok(http_version) = self.http_version.read() {
113            return http_version
114                .to_string()
115                .parse::<HttpVersion>()
116                .unwrap_or_default();
117        }
118        return HttpVersion::default();
119    }
120
121    /// Retrieves the HTTP status code associated with this response.
122    ///
123    /// # Returns
124    /// - `ResponseStatusCode`: The HTTP status code as a usize (e.g., 200 for OK, 404 for Not Found).
125    pub fn get_status_code(&self) -> ResponseStatusCode {
126        self.status_code
127    }
128
129    /// Retrieves the status text associated with the HTTP status code.
130    ///
131    /// # Returns
132    /// - `String`: The human-readable status text (e.g., "OK" for status code 200, "Not Found" for status code 404).
133    pub fn get_status_text(&self) -> String {
134        if let Ok(status_text) = self.status_text.read() {
135            return status_text.to_string();
136        }
137        return HttpStatus::default().to_string();
138    }
139
140    /// Retrieves the headers of the HTTP response.
141    ///
142    /// # Returns
143    /// - `ResponseHeaders`: A map of header names and their corresponding values as key-value pairs.
144    pub fn get_headers(&self) -> ResponseHeaders {
145        if let Ok(headers) = self.headers.read() {
146            return headers.clone();
147        }
148        return hash_map_xxhash3_64();
149    }
150
151    /// Retrieves the body content of the HTTP response.
152    ///
153    /// # Returns
154    /// - `RequestBody`: The body of the response in binary form (could be raw bytes, a stream, etc.).
155    pub fn get_body(&self) -> RequestBody {
156        if let Ok(body) = self.body.read() {
157            return body.clone();
158        }
159        return RequestBody::new();
160    }
161}
162
163impl Default for HttpResponseBinary {
164    fn default() -> Self {
165        Self {
166            http_version: Arc::new(RwLock::new(HttpVersion::Unknown(String::new()))),
167            status_code: HttpStatus::Unknown.code(),
168            status_text: Arc::new(RwLock::new(HttpStatus::Unknown.to_string())),
169            headers: Arc::new(RwLock::new(hash_map_xxhash3_64())),
170            body: Arc::new(RwLock::new(Vec::new())),
171        }
172    }
173}