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