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}