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