http_type/response/
impl.rs

1use crate::*;
2
3/// Provides a default value for `Response`.
4///
5/// Returns a new `Response` instance with all fields initialized to their default values.
6impl Default for Response {
7    fn default() -> Self {
8        let http_status: HttpStatus = HttpStatus::default();
9        Self {
10            version: HttpVersion::HTTP1_1,
11            status_code: http_status.code(),
12            reason_phrase: http_status.to_string(),
13            headers: hash_map_xx_hash3_64(),
14            body: Vec::new(),
15        }
16    }
17}
18
19impl Response {
20    /// Creates a new instance of `Response`.
21    ///
22    /// # Returns
23    ///
24    /// - `Response` - A new response instance with default values.
25    #[inline]
26    pub fn new() -> Self {
27        Self::default()
28    }
29
30    /// Retrieves the value of a response header by its key.
31    ///
32    /// # Arguments
33    ///
34    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
35    ///
36    /// # Returns
37    ///
38    /// - `OptionResponseHeadersValue` - The optional header values.
39    #[inline]
40    pub fn try_get_header<K>(&self, key: K) -> OptionResponseHeadersValue
41    where
42        K: AsRef<str>,
43    {
44        self.headers.get(key.as_ref()).cloned()
45    }
46
47    /// Retrieves the first value of a response header by its key.
48    ///
49    /// # Arguments
50    ///
51    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
52    ///
53    /// # Returns
54    ///
55    /// - `OptionResponseHeadersValueItem` - The first header value if exists.
56    #[inline]
57    pub fn try_get_header_front<K>(&self, key: K) -> OptionResponseHeadersValueItem
58    where
59        K: AsRef<str>,
60    {
61        self.headers
62            .get(key.as_ref())
63            .and_then(|values| values.front().cloned())
64    }
65
66    /// Retrieves the last value of a response header by its key.
67    ///
68    /// # Arguments
69    ///
70    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
71    ///
72    /// # Returns
73    ///
74    /// - `OptionResponseHeadersValueItem` - The last header value if exists.
75    #[inline]
76    pub fn try_get_header_back<K>(&self, key: K) -> OptionResponseHeadersValueItem
77    where
78        K: AsRef<str>,
79    {
80        self.headers
81            .get(key.as_ref())
82            .and_then(|values| values.back().cloned())
83    }
84
85    /// Checks if a header exists in the response.
86    ///
87    /// # Arguments
88    ///
89    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
90    ///
91    /// # Returns
92    ///
93    /// - `bool` - Whether the header exists.
94    #[inline]
95    pub fn has_header<K>(&self, key: K) -> bool
96    where
97        K: AsRef<str>,
98    {
99        let key: ResponseHeadersKey = key.as_ref().to_lowercase();
100        self.headers.contains_key(&key)
101    }
102
103    /// Checks if a header contains a specific value.
104    ///
105    /// # Arguments
106    ///
107    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
108    /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
109    ///
110    /// # Returns
111    ///
112    /// - `bool` - Whether the header contains the value.
113    #[inline]
114    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
115    where
116        K: AsRef<str>,
117        V: AsRef<str>,
118    {
119        if let Some(values) = self.headers.get(key.as_ref()) {
120            values.contains(&value.as_ref().to_owned())
121        } else {
122            false
123        }
124    }
125
126    /// Gets the number of headers in the response.
127    ///
128    /// # Returns
129    ///
130    /// - `usize` - The count of unique header keys.
131    #[inline]
132    pub fn get_headers_length(&self) -> usize {
133        self.headers.len()
134    }
135
136    /// Gets the number of values for a specific header key.
137    ///
138    /// # Arguments
139    ///
140    /// - `AsRef<str>` - The header key to count (must implement AsRef<str>).
141    ///
142    /// # Returns
143    ///
144    /// - `usize` - The count of values for the header.
145    #[inline]
146    pub fn get_header_length<K>(&self, key: K) -> usize
147    where
148        K: AsRef<str>,
149    {
150        self.headers
151            .get(&key.as_ref().to_lowercase())
152            .map_or(0, |values| values.len())
153    }
154
155    /// Gets the total number of header values in the response.
156    ///
157    /// This counts all values across all headers, so a header with multiple values
158    /// will contribute more than one to the total count.
159    ///
160    /// # Returns
161    ///
162    /// - `usize` - The total count of all header values.
163    #[inline]
164    pub fn get_headers_values_length(&self) -> usize {
165        self.headers.values().map(|values| values.len()).sum()
166    }
167
168    /// Retrieves the body content of the response as a UTF-8 encoded string.
169    ///
170    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
171    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
172    ///
173    /// # Returns
174    ///
175    /// - `String` - The body content as a string.
176    #[inline]
177    pub fn get_body_string(&self) -> String {
178        String::from_utf8_lossy(self.get_body()).into_owned()
179    }
180
181    /// Deserializes the body content of the response as_ref a specified type `T`.
182    ///
183    /// This method first retrieves the body content as a byte slice using `self.get_body()`.
184    /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
185    ///
186    /// # Arguments
187    ///
188    /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
189    ///
190    /// # Returns
191    ///
192    /// - `ResultJsonError<T>` - The deserialization result.
193    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
194    where
195        T: DeserializeOwned,
196    {
197        json_from_slice(self.get_body())
198    }
199
200    /// Determines whether the header should be skipped during setting.
201    ///
202    /// - Returns `true` if the header is empty or not allowed.
203    /// - Returns `false` if the header can be set.
204    #[inline]
205    fn should_skip_header(&self, key: &ResponseHeadersKey) -> bool {
206        key.trim().is_empty() || key == CONTENT_LENGTH
207    }
208
209    /// Sets a header in the response, replacing any existing values.
210    ///
211    /// This function replaces all existing values for a header with a single new value.
212    ///
213    /// # Arguments
214    ///
215    /// - `AsRef<str>` - The header key (must implement AsRef<str>).
216    /// - `AsRef<str>` - The header value (must implement AsRef<String>).
217    ///
218    /// # Returns
219    ///
220    /// - `&mut Self` - A mutable reference to self for chaining.
221    #[inline]
222    fn set_header_without_check<K, V>(&mut self, key: K, value: V) -> &mut Self
223    where
224        K: AsRef<str>,
225        V: AsRef<str>,
226    {
227        let key: ResponseHeadersKey = key.as_ref().to_lowercase();
228        let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
229        deque.push_back(value.as_ref().to_owned());
230        self.headers.insert(key, deque);
231        self
232    }
233
234    /// Sets a header in the response, replacing any existing values.
235    ///
236    /// This function replaces all existing values for a header with a single new value.
237    ///
238    /// # Arguments
239    ///
240    /// - `AsRef<str>` - The header key (must implement AsRef<str>).
241    /// - `AsRef<str>` - The header value (must implement AsRef<String>).
242    ///
243    /// # Returns
244    ///
245    /// - `&mut Self` - A mutable reference to self for chaining.
246    #[inline]
247    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
248    where
249        K: AsRef<str>,
250        V: AsRef<str>,
251    {
252        let key: ResponseHeadersKey = key.as_ref().to_lowercase();
253        if self.should_skip_header(&key) {
254            return self;
255        }
256        let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
257        deque.push_back(value.as_ref().to_owned());
258        self.headers.insert(key, deque);
259        self
260    }
261
262    /// Adds a header to the response.
263    ///
264    /// This function appends a value to the response headers.
265    /// If the header already exists, the new value will be added to the existing values.
266    ///
267    /// # Arguments
268    ///
269    /// - `AsRef<str>` - The header key (must implement AsRef<str>).
270    /// - `AsRef<str>` - The header value (must implement AsRef<String>).
271    ///
272    /// # Returns
273    ///
274    /// - `&mut Self` - A mutable reference to self for chaining.
275    #[inline]
276    pub fn add_header<K, V>(&mut self, key: K, value: V) -> &mut Self
277    where
278        K: AsRef<str>,
279        V: AsRef<str>,
280    {
281        let key: ResponseHeadersKey = key.as_ref().to_lowercase();
282        if self.should_skip_header(&key) {
283            return self;
284        }
285        self.headers
286            .entry(key)
287            .or_default()
288            .push_back(value.as_ref().to_owned());
289        self
290    }
291
292    /// Removes a header from the response.
293    ///
294    /// This function removes all values for the specified header key.
295    ///
296    /// # Arguments
297    ///
298    /// - `AsRef<str>` - The header key to remove (must implement AsRef<str>).
299    ///
300    /// # Returns
301    ///
302    /// - `&mut Self` - A mutable reference to self for chaining.
303    #[inline]
304    pub fn remove_header<K>(&mut self, key: K) -> &mut Self
305    where
306        K: AsRef<str>,
307    {
308        let _ = self.headers.remove(&key.as_ref().to_lowercase()).is_some();
309        self
310    }
311
312    /// Removes a specific value from a header in the response.
313    ///
314    /// This function removes only the specified value from the header.
315    /// If the header has multiple values, only the matching value is removed.
316    /// If this was the last value for the header, the entire header is removed.
317    ///
318    /// # Arguments
319    ///
320    /// - `AsRef<str>` - The header key (must implement AsRef<str>).
321    /// - `AsRef<str>` - The value to remove (must implement AsRef<String>).
322    ///
323    /// # Returns
324    ///
325    /// - `&mut Self` - A mutable reference to self for chaining.
326    #[inline]
327    pub fn remove_header_value<K, V>(&mut self, key: K, value: V) -> &mut Self
328    where
329        K: AsRef<str>,
330        V: AsRef<str>,
331    {
332        let key: ResponseHeadersKey = key.as_ref().to_lowercase();
333        if let Some(values) = self.headers.get_mut(&key) {
334            values.retain(|v| v != &value.as_ref().to_owned());
335            if values.is_empty() {
336                self.headers.remove(&key);
337            }
338        }
339        self
340    }
341
342    /// Clears all headers from the response.
343    ///
344    /// This function removes all headers, leaving the headers map empty.
345    ///
346    /// # Returns
347    ///
348    /// - `&mut Self` - A mutable reference to self for chaining.
349    #[inline]
350    pub fn clear_headers(&mut self) -> &mut Self {
351        self.headers.clear();
352        self
353    }
354
355    /// Sets the body of the response.
356    ///
357    /// This method allows you to set the body of the response by converting the provided
358    /// value as_ref a `ResponseBody` type. The `body` is updated with the converted value.
359    ///
360    /// # Arguments
361    ///
362    /// - `AsRef<[u8]>` - The body content (must implement AsRef<[u8]>).
363    ///
364    /// # Returns
365    ///
366    /// - `&mut Self` - A mutable reference to self for chaining.
367    #[inline]
368    pub fn set_body<T>(&mut self, body: T) -> &mut Self
369    where
370        T: AsRef<[u8]>,
371    {
372        self.body = body.as_ref().to_owned();
373        self
374    }
375
376    /// Sets the reason phrase of the response.
377    ///
378    /// This method allows you to set the reason phrase of the response by converting the
379    /// provided value as_ref a `ResponseReasonPhrase` type. The `reason_phrase` is updated
380    /// with the converted value.
381    ///
382    /// # Arguments
383    ///
384    /// - `AsRef<str>` - The reason phrase (must implement AsRef<str>).
385    ///
386    /// # Returns
387    ///
388    /// - `&mut Self` - A mutable reference to self for chaining.
389    #[inline]
390    pub fn set_reason_phrase<T>(&mut self, reason_phrase: T) -> &mut Self
391    where
392        T: AsRef<str>,
393    {
394        self.reason_phrase = reason_phrase.as_ref().to_owned();
395        self
396    }
397
398    /// Pushes a header with a key and value as_ref the response string.
399    ///
400    /// # Arguments
401    ///
402    /// - `&mut String`: A mutable reference to the string where the header will be added.
403    /// - `&str`: The header key as a string slice (`&str`).
404    /// - `&str`: The header value as a string slice (`&str`).
405    #[inline]
406    fn push_header(response_string: &mut String, key: &str, value: &str) {
407        response_string.push_str(key);
408        response_string.push_str(COLON);
409        response_string.push_str(value);
410        response_string.push_str(HTTP_BR);
411    }
412
413    /// Pushes the first line of an HTTP response (version, status code, and reason phrase) as_ref the response string.
414    /// This corresponds to the status line of the HTTP response.
415    ///
416    /// # Arguments
417    ///
418    /// - `response_string`: A mutable reference to the string where the first line will be added.
419    #[inline]
420    fn push_http_first_line(&self, response_string: &mut String) {
421        response_string.push_str(&self.get_version().to_string());
422        response_string.push_str(SPACE);
423        response_string.push_str(&self.get_status_code().to_string());
424        response_string.push_str(SPACE);
425        response_string.push_str(self.get_reason_phrase());
426        response_string.push_str(HTTP_BR);
427    }
428
429    /// Builds the full HTTP response as a byte vector.
430    ///
431    /// This method constructs the complete HTTP response, including the status line,
432    /// headers, and body. It handles content encoding, content type, connection
433    /// management, and content length.
434    ///
435    /// # Returns
436    ///
437    /// - `ResponseData` - The complete HTTP response bytes.
438    pub fn build(&mut self) -> ResponseData {
439        if self.reason_phrase.is_empty() {
440            self.set_reason_phrase(HttpStatus::phrase(*self.get_status_code()));
441        }
442        let mut response_string: String = String::with_capacity(DEFAULT_BUFFER_SIZE);
443        self.push_http_first_line(&mut response_string);
444        let compress_type_opt: OptionCompress = self
445            .try_get_header_back(CONTENT_ENCODING)
446            .map(|value| value.parse::<Compress>().unwrap_or_default());
447        if self.try_get_header_back(CONNECTION).is_none() {
448            self.set_header_without_check(CONNECTION, KEEP_ALIVE);
449        }
450        let content_type: ResponseHeadersValueItem =
451            self.try_get_header_back(CONTENT_TYPE).unwrap_or_else(|| {
452                let mut content_type: String = String::with_capacity(
453                    TEXT_HTML.len() + SEMICOLON_SPACE.len() + CHARSET_UTF_8.len(),
454                );
455                content_type.push_str(TEXT_HTML);
456                content_type.push_str(SEMICOLON_SPACE);
457                content_type.push_str(CHARSET_UTF_8);
458                self.set_header_without_check(CONTENT_TYPE, &content_type);
459                content_type
460            });
461        let mut body: ResponseBody = self.get_body().clone();
462        if let Some(compress_type) = compress_type_opt
463            && !compress_type.is_unknown()
464        {
465            body = compress_type
466                .encode(&body, DEFAULT_BUFFER_SIZE)
467                .into_owned();
468        }
469        if !content_type.eq_ignore_ascii_case(TEXT_EVENT_STREAM) {
470            self.set_header_without_check(CONTENT_LENGTH, body.len().to_string());
471        }
472        self.get_headers().iter().for_each(|(key, values)| {
473            for value in values.iter() {
474                Self::push_header(&mut response_string, key, value);
475            }
476        });
477        response_string.push_str(HTTP_BR);
478        let mut response_bytes: Vec<u8> = response_string.into_bytes();
479        response_bytes.extend_from_slice(&body);
480        response_bytes
481    }
482
483    /// Converts the response to a formatted string representation.
484    ///
485    /// This method provides a human-readable summary of the response, including its version,
486    /// status code, reason phrase, headers, and body information.
487    ///
488    /// # Returns
489    ///
490    /// A `String` containing formatted response details.
491    #[inline]
492    pub fn get_string(&self) -> String {
493        let body: &Vec<u8> = self.get_body();
494        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
495            PLAIN
496        } else {
497            BINARY
498        };
499        format!(
500            "[Response] => [version]: {}; [status code]: {}; [reason]: {}; [headers]: {:?}; [body]: {} bytes {};",
501            self.get_version(),
502            self.get_status_code(),
503            self.get_reason_phrase(),
504            self.get_headers(),
505            body.len(),
506            body_type
507        )
508    }
509}