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