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