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}