http_request/response/response_text/
impl.rs

1use super::r#type::HttpResponseText;
2use crate::response::{r#trait::ResponseTrait, response_binary::r#type::HttpResponseBinary};
3use http_compress::Compress;
4use http_type::*;
5use std::{
6    collections::HashMap,
7    sync::{Arc, RwLock},
8};
9
10/// Implements the `ResponseTrait` trait for `HttpResponseText`.
11///
12/// This implementation allows `HttpResponseText` to convert between text and binary
13/// representations of HTTP responses. It provides methods for parsing raw responses, as well
14/// as accessing text and binary formats.
15///
16/// # Associated Types
17/// - `OutputText`: Specifies the text representation of an HTTP response (`HttpResponseText`).
18/// - `OutputBinary`: Specifies the binary representation of an HTTP response (`HttpResponseBinary`).
19impl ResponseTrait for HttpResponseText {
20    type OutputText = HttpResponseText;
21    type OutputBinary = HttpResponseBinary;
22
23    #[inline]
24    fn from(response: &[u8]) -> Self::OutputText
25    where
26        Self: Sized,
27    {
28        <HttpResponseBinary as ResponseTrait>::from(response).text()
29    }
30
31    #[inline]
32    fn text(&self) -> Self::OutputText {
33        self.clone()
34    }
35
36    #[inline]
37    fn binary(&self) -> HttpResponseBinary {
38        let body: Vec<u8> = self
39            .body
40            .read()
41            .map_or(Vec::new(), |body| body.clone().into_bytes());
42        HttpResponseBinary {
43            http_version: self.http_version.clone(),
44            status_code: self.status_code,
45            status_text: self.status_text.clone(),
46            headers: self.headers.clone(),
47            body: Arc::new(RwLock::new(body)),
48        }
49    }
50
51    #[inline]
52    fn decode(&self, buffer_size: usize) -> HttpResponseBinary {
53        let http_response: HttpResponseText = self.clone();
54        let tmp_body: Vec<u8> = self
55            .body
56            .read()
57            .map_or(Vec::new(), |body| body.as_bytes().to_vec())
58            .to_vec();
59        let body: Vec<u8> = Compress::from(
60            &self
61                .headers
62                .read()
63                .map_or(HashMap::new(), |headers| headers.clone()),
64        )
65        .decode(&tmp_body, buffer_size)
66        .into_owned();
67        HttpResponseBinary {
68            http_version: http_response.http_version,
69            status_code: http_response.status_code,
70            status_text: http_response.status_text,
71            headers: http_response.headers,
72            body: Arc::new(RwLock::new(body)),
73        }
74    }
75}
76
77impl HttpResponseText {
78    /// Retrieves the HTTP version associated with this response.
79    ///
80    /// # Returns
81    /// - `HttpVersion`: The HTTP version (e.g., HTTP/1.1, HTTP/2, etc.) used for the response.
82    #[inline]
83    pub fn get_http_version(&self) -> HttpVersion {
84        if let Ok(http_version) = self.http_version.read() {
85            return http_version
86                .to_string()
87                .parse::<HttpVersion>()
88                .unwrap_or_default();
89        }
90        return HttpVersion::default();
91    }
92
93    /// Retrieves the HTTP status code associated with this response.
94    ///
95    /// # Returns
96    /// - `StatusCodeUsize`: The HTTP status code as a usize (e.g., 200 for OK, 404 for Not Found).
97    #[inline]
98    pub fn get_status_code(&self) -> StatusCodeUsize {
99        self.status_code
100    }
101
102    /// Retrieves the status text associated with the HTTP status code.
103    ///
104    /// # Returns
105    /// - `String`: The human-readable status text (e.g., "OK" for status code 200, "Not Found" for status code 404).
106    #[inline]
107    pub fn get_status_text(&self) -> String {
108        if let Ok(status_text) = self.status_text.read() {
109            return status_text.to_string();
110        }
111        return StatusCode::default().to_string();
112    }
113
114    /// Retrieves the headers of the HTTP response.
115    ///
116    /// # Returns
117    /// - `HttpHeaderMap`: A map of header names and their corresponding values as key-value pairs.
118    #[inline]
119    pub fn get_headers(&self) -> HttpHeaderMap {
120        if let Ok(headers) = self.headers.read() {
121            return headers.clone();
122        }
123        return HttpHeaderMap::new();
124    }
125
126    /// Retrieves the body content of the HTTP response as a `String`.
127    ///
128    /// This method attempts to read the body of the response. If the body can be successfully read,
129    /// it is converted into a `String` and returned. If reading the body fails, an empty string is returned.
130    ///
131    /// # Returns
132    /// - `HttpBodyString`: The body of the response as a string. If the body could not be read,
133    ///   an empty string is returned.
134    #[inline]
135    pub fn get_body(&self) -> HttpBodyString {
136        if let Ok(body) = self.body.read() {
137            return body.to_string();
138        }
139        return HttpBodyString::new();
140    }
141}
142
143impl Default for HttpResponseText {
144    #[inline]
145    fn default() -> Self {
146        Self {
147            http_version: Arc::new(RwLock::new(HttpVersion::Unknown(String::new()))),
148            status_code: StatusCode::Unknown.code(),
149            status_text: Arc::new(RwLock::new(StatusCode::Unknown.to_string())),
150            headers: Arc::new(RwLock::new(HashMap::new())),
151            body: Arc::new(RwLock::new(String::new())),
152        }
153    }
154}