http_type/response/
impl.rs

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