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