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