http_type/response/
impl.rs

1use crate::*;
2
3impl Default for Response {
4    fn default() -> Self {
5        Self::new()
6    }
7}
8
9impl Response {
10    /// Creates a new instance of `Response`.
11    ///
12    /// # Returns
13    /// - An initialized `Response` with default values.
14    pub fn new() -> Self {
15        Response {
16            version: HttpVersion::HTTP1_1,
17            status_code: 200,
18            reason_phrase: EMPTY_STR.to_owned(),
19            headers: hash_map_xx_hash3_64(),
20            body: Vec::new(),
21        }
22    }
23
24    /// Retrieves the value of a response header by its key.
25    ///
26    /// # Parameters
27    /// - `key`: The header's key, which can be of any type that implements `Into<ResponseHeadersKey>`.
28    ///
29    /// # Returns
30    /// - `OptionResponseHeadersValue`: Returns `Some(value)` if the key exists in the response headers,
31    ///   or `None` if the key does not exist.
32    pub fn get_header<K>(&self, key: K) -> OptionResponseHeadersValue
33    where
34        K: Into<ResponseHeadersKey>,
35    {
36        self.headers
37            .get(&key.into())
38            .and_then(|data| Some(data.clone()))
39    }
40
41    /// Retrieves the first value of a response header by its key.
42    ///
43    /// # Parameters
44    /// - `key`: The header's key, which can be of any type that implements `Into<ResponseHeadersKey>`.
45    ///
46    /// # Returns
47    /// - `OptionResponseHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
48    ///   or `None` if the key does not exist or has no values.
49    pub fn get_header_front<K>(&self, key: K) -> OptionResponseHeadersValueItem
50    where
51        K: Into<ResponseHeadersKey>,
52    {
53        self.headers
54            .get(&key.into())
55            .and_then(|values| values.front().cloned())
56    }
57
58    /// Retrieves the last value of a response header by its key.
59    ///
60    /// # Parameters
61    /// - `key`: The header's key, which can be of any type that implements `Into<ResponseHeadersKey>`.
62    ///
63    /// # Returns
64    /// - `OptionResponseHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
65    ///   or `None` if the key does not exist or has no values.
66    pub fn get_header_back<K>(&self, key: K) -> OptionResponseHeadersValueItem
67    where
68        K: Into<ResponseHeadersKey>,
69    {
70        self.headers
71            .get(&key.into())
72            .and_then(|values| values.back().cloned())
73    }
74
75    /// Checks if a header exists in the response.
76    ///
77    /// # Parameters
78    /// - `key`: The header key to check, which will be converted into a `ResponseHeadersKey`.
79    ///
80    /// # Returns
81    /// - `true`: If the header exists.
82    /// - `false`: If the header does not exist.
83    pub fn has_header<K>(&self, key: K) -> bool
84    where
85        K: Into<ResponseHeadersKey>,
86    {
87        let key: ResponseHeadersKey = key.into().to_lowercase();
88        self.headers.contains_key(&key)
89    }
90
91    /// Checks if a header contains a specific value.
92    ///
93    /// # Parameters
94    /// - `key`: The header key to check, which will be converted into a `ResponseHeadersKey`.
95    /// - `value`: The value to search for in the header.
96    ///
97    /// # Returns
98    /// - `true`: If the header exists and contains the specified value.
99    /// - `false`: If the header does not exist or does not contain the value.
100    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
101    where
102        K: Into<ResponseHeadersKey>,
103        V: Into<ResponseHeadersValueItem>,
104    {
105        let key: ResponseHeadersKey = key.into();
106        let value: ResponseHeadersValueItem = value.into();
107        if let Some(values) = self.headers.get(&key) {
108            values.contains(&value)
109        } else {
110            false
111        }
112    }
113
114    /// Gets the number of headers in the response.
115    ///
116    /// # Returns
117    /// - The number of unique header keys in the response.
118    pub fn get_headers_len(&self) -> usize {
119        self.headers.len()
120    }
121
122    /// Gets the number of values for a specific header key.
123    ///
124    /// # Parameters
125    /// - `key`: The header key to count values for, which will be converted into a `ResponseHeadersKey`.
126    ///
127    /// # Returns
128    /// - The number of values for the specified header key. Returns 0 if the header does not exist.
129    pub fn get_header_len<K>(&self, key: K) -> usize
130    where
131        K: Into<ResponseHeadersKey>,
132    {
133        let key: ResponseHeadersKey = key.into().to_lowercase();
134        self.headers.get(&key).map_or(0, |values| values.len())
135    }
136
137    /// Gets the total number of header values in the response.
138    ///
139    /// This counts all values across all headers, so a header with multiple values
140    /// will contribute more than one to the total count.
141    ///
142    /// # Returns
143    /// - The total number of header values in the response.
144    pub fn get_headers_values_len(&self) -> usize {
145        self.headers.values().map(|values| values.len()).sum()
146    }
147
148    /// Retrieves the body content of the object as a UTF-8 encoded string.
149    ///
150    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
151    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
152    ///
153    /// # Returns
154    /// A `String` containing the body content.
155    pub fn get_body_string(&self) -> String {
156        String::from_utf8_lossy(self.get_body()).into_owned()
157    }
158
159    /// Deserializes the body content of the object into a specified type `T`.
160    ///
161    /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
162    /// It then attempts to deserialize the string into the specified type `T` using `json_from_slice`.
163    ///
164    /// # Type Parameters
165    /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
166    ///
167    /// # Returns
168    /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
169    /// - `Err(ResultJsonError)`: An error if the deserialization fails (e.g., invalid JSON format or type mismatch).
170    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
171    where
172        T: DeserializeOwned,
173    {
174        json_from_slice(self.get_body())
175    }
176
177    /// Adds a header to the response.
178    ///
179    /// This function appends a value to the response headers.
180    /// If the header already exists, the new value will be added to the existing values.
181    ///
182    /// # Parameters
183    /// - `key`: The header key, which will be converted into a `ResponseHeadersKey`.
184    /// - `value`: The value of the header, which will be converted into a String.
185    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
186    where
187        K: Into<ResponseHeadersKey>,
188        V: Into<String>,
189    {
190        let key: ResponseHeadersKey = key.into().to_lowercase();
191        if key.trim().is_empty() || key == CONTENT_LENGTH {
192            return self;
193        }
194        let value: String = value.into();
195        self.headers
196            .entry(key)
197            .or_insert_with(VecDeque::new)
198            .push_front(value);
199        self
200    }
201
202    /// Replaces all values for a header in the response.
203    ///
204    /// This function replaces all existing values for a header with a single new value.
205    ///
206    /// # Parameters
207    /// - `key`: The header key, which will be converted into a `ResponseHeadersKey`.
208    /// - `value`: The value of the header, which will be converted into a String.
209    pub fn replace_header<K, V>(&mut self, key: K, value: V) -> &mut Self
210    where
211        K: Into<ResponseHeadersKey>,
212        V: Into<String>,
213    {
214        let key: ResponseHeadersKey = key.into().to_lowercase();
215        if key.trim().is_empty() {
216            return self;
217        }
218        let value: String = value.into();
219        let mut deque: VecDeque<String> = VecDeque::new();
220        deque.push_front(value);
221        self.headers.insert(key, deque);
222        self
223    }
224
225    /// Removes a header from the response.
226    ///
227    /// This function removes all values for the specified header key.
228    ///
229    /// # Parameters
230    /// - `key`: The header key to remove, which will be converted into a `ResponseHeadersKey`.
231    pub fn remove_header<K>(&mut self, key: K) -> &mut Self
232    where
233        K: Into<ResponseHeadersKey>,
234    {
235        let key: ResponseHeadersKey = key.into().to_lowercase();
236        let _ = self.headers.remove(&key).is_some();
237        self
238    }
239
240    /// Removes a specific value from a header in the response.
241    ///
242    /// This function removes only the specified value from the header.
243    /// If the header has multiple values, only the matching value is removed.
244    /// If this was the last value for the header, the entire header is removed.
245    ///
246    /// # Parameters
247    /// - `key`: The header key, which will be converted into a `ResponseHeadersKey`.
248    /// - `value`: The specific value to remove from the header.
249    pub fn remove_header_value<K, V>(&mut self, key: K, value: V) -> &mut Self
250    where
251        K: Into<ResponseHeadersKey>,
252        V: Into<String>,
253    {
254        let key: ResponseHeadersKey = key.into().to_lowercase();
255        let value: String = value.into();
256        if let Some(values) = self.headers.get_mut(&key) {
257            values.retain(|v| v != &value);
258            if values.is_empty() {
259                self.headers.remove(&key);
260            }
261        }
262        self
263    }
264
265    /// Clears all headers from the response.
266    ///
267    /// This function removes all headers, leaving the headers map empty.
268    pub fn clear_headers(&mut self) -> &mut Self {
269        self.headers.clear();
270        self
271    }
272
273    /// Set the body of the response.
274    ///
275    /// This method allows you to set the body of the response by converting the provided
276    /// value into a `ResponseBody` type. The `body` is updated with the converted value,
277    /// and the method returns a mutable reference to the current instance for method chaining.
278    ///
279    /// # Parameters
280    /// - `body`: The body of the response to be set. It can be any type that can be converted
281    ///   into a `ResponseBody` using the `Into` trait.
282    ///
283    /// # Return Value
284    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
285    /// Set the body of the response.
286    ///
287    /// This method allows you to set the body of the response by converting the provided
288    /// value into a `ResponseBody` type. The `body` is updated with the converted value,
289    /// and the method returns a mutable reference to the current instance for method chaining.
290    ///
291    /// # Parameters
292    /// - `body`: The body of the response to be set. It can be any type that can be converted
293    ///   into a `ResponseBody` using the `Into` trait.
294    ///
295    /// # Return Value
296    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
297    pub fn set_body<T>(&mut self, body: T) -> &mut Self
298    where
299        T: Into<ResponseBody>,
300    {
301        self.body = body.into();
302        self
303    }
304
305    /// Set the reason phrase of the response.
306    ///
307    /// This method allows you to set the reason phrase of the response by converting the
308    /// provided value into a `ResponseReasonPhrase` type. The `reason_phrase` is updated
309    /// with the converted value, and the method returns a mutable reference to the current
310    /// instance for method chaining.
311    ///
312    /// # Parameters
313    /// - `reason_phrase`: The reason phrase to be set for the response. It can be any type
314    ///   that can be converted into a `ResponseReasonPhrase` using the `Into` trait.
315    ///
316    /// # Return Value
317    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
318    pub fn set_reason_phrase<T>(&mut self, reason_phrase: T) -> &mut Self
319    where
320        T: Into<ResponseReasonPhrase>,
321    {
322        self.reason_phrase = reason_phrase.into();
323        self
324    }
325
326    /// Pushes a header with a key and value into the response string.
327    ///
328    /// # Parameters
329    /// - `response_string`: A mutable reference to the string where the header will be added.
330    /// - `key`: The header key as a string slice (`&str`).
331    /// - `value`: The header value as a string slice (`&str`).
332    pub(super) fn push_header(response_string: &mut String, key: &str, value: &str) {
333        response_string.push_str(key);
334        response_string.push_str(COLON_SPACE);
335        response_string.push_str(value);
336        response_string.push_str(HTTP_BR);
337    }
338
339    /// Pushes the first line of an HTTP response (version, status code, and reason phrase) into the response string.
340    /// This corresponds to the status line of the HTTP response.
341    ///
342    /// # Parameters
343    /// - `response_string`: A mutable reference to the string where the first line will be added.
344    pub(super) fn push_http_response_first_line(&self, response_string: &mut String) {
345        response_string.push_str(&self.get_version().to_string());
346        response_string.push_str(SPACE);
347        response_string.push_str(&self.get_status_code().to_string());
348        response_string.push_str(SPACE);
349        response_string.push_str(self.get_reason_phrase());
350        response_string.push_str(HTTP_BR);
351    }
352
353    /// Builds the full HTTP response as a byte vector.
354    /// # Returns
355    /// - `ResponseData`: response data
356    pub fn build(&mut self) -> ResponseData {
357        if self.reason_phrase.is_empty() {
358            self.set_reason_phrase(HttpStatus::phrase(*self.get_status_code()));
359        }
360        let mut response_string: String = String::new();
361        self.push_http_response_first_line(&mut response_string);
362        let mut compress_type_opt: OptionCompress = None;
363        let mut connection_opt: OptionString = None;
364        let mut content_type_opt: OptionString = None;
365        let headers: ResponseHeaders = self
366            .get_mut_headers()
367            .drain()
368            .map(|(key, value)| (key.to_lowercase(), value))
369            .collect();
370        let mut unset_content_length: bool = false;
371        for (key, values) in headers.iter() {
372            for value in values.iter().rev() {
373                if key == CONTENT_ENCODING {
374                    compress_type_opt = Some(value.parse::<Compress>().unwrap_or_default());
375                } else if key == CONNECTION {
376                    connection_opt = Some(value.to_owned());
377                } else if key == CONTENT_TYPE {
378                    content_type_opt = Some(value.to_owned());
379                    if value.eq_ignore_ascii_case(TEXT_EVENT_STREAM) {
380                        unset_content_length = true;
381                    }
382                }
383                Self::push_header(&mut response_string, key, value);
384            }
385        }
386        if connection_opt.is_none() {
387            Self::push_header(&mut response_string, CONNECTION, KEEP_ALIVE);
388        }
389        if content_type_opt.is_none() {
390            let mut content_type: String = String::with_capacity(
391                TEXT_HTML.len() + SEMICOLON_SPACE.len() + CHARSET_UTF_8.len(),
392            );
393            content_type.push_str(TEXT_HTML);
394            content_type.push_str(SEMICOLON_SPACE);
395            content_type.push_str(CHARSET_UTF_8);
396            Self::push_header(&mut response_string, CONTENT_TYPE, &content_type);
397        }
398        let mut body: Cow<Vec<u8>> = Cow::Borrowed(self.get_body());
399        if !unset_content_length {
400            if let Some(compress_type) = compress_type_opt {
401                if !compress_type.is_unknown() {
402                    let tmp_body: Cow<'_, Vec<u8>> =
403                        compress_type.encode(&body, DEFAULT_BUFFER_SIZE);
404                    body = Cow::Owned(tmp_body.into_owned());
405                }
406            }
407            let len_string: String = body.len().to_string();
408            Self::push_header(&mut response_string, CONTENT_LENGTH, &len_string);
409        }
410        response_string.push_str(HTTP_BR);
411        let mut response_bytes: Vec<u8> = response_string.into_bytes();
412        response_bytes.extend_from_slice(&body);
413        response_bytes
414    }
415
416    /// Converts the response to a formatted string representation.
417    ///
418    /// - Returns: A `String` containing formatted response details.
419    pub fn get_string(&self) -> String {
420        let body: &Vec<u8> = self.get_body();
421        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
422            PLAIN
423        } else {
424            BINARY
425        };
426        format!(
427            "[Response] => [version]: {}; [status code]: {}; [reason]: {}; [headers]: {:?}; [body]: {} bytes {};",
428            self.get_version(),
429            self.get_status_code(),
430            self.get_reason_phrase(),
431            self.get_headers(),
432            body.len(),
433            body_type
434        )
435    }
436}