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