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