Skip to main content

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