http_type/response/impl.rs
1use crate::*;
2
3/// Provides a default value for `Response`.
4///
5/// Returns a new `Response` instance with all fields initialized to their default values.
6impl Default for Response {
7 fn default() -> Self {
8 Self {
9 version: HttpVersion::default(),
10 status_code: ResponseStatusCode::default(),
11 reason_phrase: ResponseReasonPhrase::default(),
12 headers: hash_map_xx_hash3_64(),
13 body: Vec::new(),
14 }
15 }
16}
17
18impl Response {
19 /// Creates a new instance of `Response`.
20 ///
21 /// # Returns
22 ///
23 /// - `Response` - A new response instance with default values.
24 #[inline]
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 /// Retrieves the value of a response header by its key.
30 ///
31 /// # Arguments
32 ///
33 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
34 ///
35 /// # Returns
36 ///
37 /// - `OptionResponseHeadersValue` - The optional header values.
38 #[inline]
39 pub fn try_get_header<K>(&self, key: K) -> OptionResponseHeadersValue
40 where
41 K: AsRef<str>,
42 {
43 self.headers
44 .get(key.as_ref())
45 .and_then(|data| Some(data.clone()))
46 }
47
48 /// Retrieves the first value of a response header by its key.
49 ///
50 /// # Arguments
51 ///
52 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
53 ///
54 /// # Returns
55 ///
56 /// - `OptionResponseHeadersValueItem` - The first header value if exists.
57 #[inline]
58 pub fn try_get_header_front<K>(&self, key: K) -> OptionResponseHeadersValueItem
59 where
60 K: AsRef<str>,
61 {
62 self.headers
63 .get(key.as_ref())
64 .and_then(|values| values.front().cloned())
65 }
66
67 /// Retrieves the last value of a response header by its key.
68 ///
69 /// # Arguments
70 ///
71 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
72 ///
73 /// # Returns
74 ///
75 /// - `OptionResponseHeadersValueItem` - The last header value if exists.
76 #[inline]
77 pub fn try_get_header_back<K>(&self, key: K) -> OptionResponseHeadersValueItem
78 where
79 K: AsRef<str>,
80 {
81 self.headers
82 .get(key.as_ref())
83 .and_then(|values| values.back().cloned())
84 }
85
86 /// Checks if a header exists in the response.
87 ///
88 /// # Arguments
89 ///
90 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
91 ///
92 /// # Returns
93 ///
94 /// - `bool` - Whether the header exists.
95 #[inline]
96 pub fn has_header<K>(&self, key: K) -> bool
97 where
98 K: AsRef<str>,
99 {
100 let key: ResponseHeadersKey = key.as_ref().to_lowercase();
101 self.headers.contains_key(&key)
102 }
103
104 /// Checks if a header contains a specific value.
105 ///
106 /// # Arguments
107 ///
108 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
109 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
110 ///
111 /// # Returns
112 ///
113 /// - `bool` - Whether the header contains the value.
114 #[inline]
115 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
116 where
117 K: AsRef<str>,
118 V: AsRef<str>,
119 {
120 if let Some(values) = self.headers.get(key.as_ref()) {
121 values.contains(&value.as_ref().to_owned())
122 } else {
123 false
124 }
125 }
126
127 /// Gets the number of headers in the response.
128 ///
129 /// # Returns
130 ///
131 /// - `usize` - The count of unique header keys.
132 #[inline]
133 pub fn get_headers_length(&self) -> usize {
134 self.headers.len()
135 }
136
137 /// Gets the number of values for a specific header key.
138 ///
139 /// # Arguments
140 ///
141 /// - `AsRef<str>` - The header key to count (must implement AsRef<str>).
142 ///
143 /// # Returns
144 ///
145 /// - `usize` - The count of values for the header.
146 #[inline]
147 pub fn get_header_length<K>(&self, key: K) -> usize
148 where
149 K: AsRef<str>,
150 {
151 self.headers
152 .get(&key.as_ref().to_lowercase())
153 .map_or(0, |values| values.len())
154 }
155
156 /// Gets the total number of header values in the response.
157 ///
158 /// This counts all values across all headers, so a header with multiple values
159 /// will contribute more than one to the total count.
160 ///
161 /// # Returns
162 ///
163 /// - `usize` - The total count of all header values.
164 #[inline]
165 pub fn get_headers_values_length(&self) -> usize {
166 self.headers.values().map(|values| values.len()).sum()
167 }
168
169 /// Retrieves the body content of the response as a UTF-8 encoded string.
170 ///
171 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
172 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
173 ///
174 /// # Returns
175 ///
176 /// - `String` - The body content as a string.
177 #[inline]
178 pub fn get_body_string(&self) -> String {
179 String::from_utf8_lossy(self.get_body()).into_owned()
180 }
181
182 /// Deserializes the body content of the response as_ref a specified type `T`.
183 ///
184 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
185 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
186 ///
187 /// # Arguments
188 ///
189 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
190 ///
191 /// # Returns
192 ///
193 /// - `ResultJsonError<T>` - The deserialization result.
194 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
195 where
196 T: DeserializeOwned,
197 {
198 json_from_slice(self.get_body())
199 }
200
201 /// Determines whether the header should be skipped during setting.
202 ///
203 /// - Returns `true` if the header is empty or not allowed.
204 /// - Returns `false` if the header can be set.
205 #[inline]
206 fn should_skip_header(&self, key: &ResponseHeadersKey) -> bool {
207 key.trim().is_empty() || key == CONTENT_LENGTH
208 }
209
210 /// Sets a header in the response, replacing any existing values.
211 ///
212 /// This function replaces all existing values for a header with a single new value.
213 ///
214 /// # Arguments
215 ///
216 /// - `AsRef<str>` - The header key (must implement AsRef<str>).
217 /// - `AsRef<str>` - The header value (must implement AsRef<String>).
218 ///
219 /// # Returns
220 ///
221 /// - `&mut Self` - A mutable reference to self for chaining.
222 #[inline]
223 fn set_header_without_check<K, V>(&mut self, key: K, value: V) -> &mut Self
224 where
225 K: AsRef<str>,
226 V: AsRef<str>,
227 {
228 let key: ResponseHeadersKey = key.as_ref().to_lowercase();
229 let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
230 deque.push_back(value.as_ref().to_owned());
231 self.headers.insert(key, deque);
232 self
233 }
234
235 /// Sets a header in the response, replacing any existing values.
236 ///
237 /// This function replaces all existing values for a header with a single new value.
238 ///
239 /// # Arguments
240 ///
241 /// - `AsRef<str>` - The header key (must implement AsRef<str>).
242 /// - `AsRef<str>` - The header value (must implement AsRef<String>).
243 ///
244 /// # Returns
245 ///
246 /// - `&mut Self` - A mutable reference to self for chaining.
247 #[inline]
248 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
249 where
250 K: AsRef<str>,
251 V: AsRef<str>,
252 {
253 let key: ResponseHeadersKey = key.as_ref().to_lowercase();
254 if self.should_skip_header(&key) {
255 return self;
256 }
257 let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
258 deque.push_back(value.as_ref().to_owned());
259 self.headers.insert(key, deque);
260 self
261 }
262
263 /// Adds a header to the response.
264 ///
265 /// This function appends a value to the response headers.
266 /// If the header already exists, the new value will be added to the existing values.
267 ///
268 /// # Arguments
269 ///
270 /// - `AsRef<str>` - The header key (must implement AsRef<str>).
271 /// - `AsRef<str>` - The header value (must implement AsRef<String>).
272 ///
273 /// # Returns
274 ///
275 /// - `&mut Self` - A mutable reference to self for chaining.
276 #[inline]
277 pub fn add_header<K, V>(&mut self, key: K, value: V) -> &mut Self
278 where
279 K: AsRef<str>,
280 V: AsRef<str>,
281 {
282 let key: ResponseHeadersKey = key.as_ref().to_lowercase();
283 if self.should_skip_header(&key) {
284 return self;
285 }
286 self.headers
287 .entry(key)
288 .or_insert_with(VecDeque::new)
289 .push_back(value.as_ref().to_owned());
290 self
291 }
292
293 /// Removes a header from the response.
294 ///
295 /// This function removes all values for the specified header key.
296 ///
297 /// # Arguments
298 ///
299 /// - `AsRef<str>` - The header key to remove (must implement AsRef<str>).
300 ///
301 /// # Returns
302 ///
303 /// - `&mut Self` - A mutable reference to self for chaining.
304 #[inline]
305 pub fn remove_header<K>(&mut self, key: K) -> &mut Self
306 where
307 K: AsRef<str>,
308 {
309 let _ = self.headers.remove(&key.as_ref().to_lowercase()).is_some();
310 self
311 }
312
313 /// Removes a specific value from a header in the response.
314 ///
315 /// This function removes only the specified value from the header.
316 /// If the header has multiple values, only the matching value is removed.
317 /// If this was the last value for the header, the entire header is removed.
318 ///
319 /// # Arguments
320 ///
321 /// - `AsRef<str>` - The header key (must implement AsRef<str>).
322 /// - `AsRef<str>` - The value to remove (must implement AsRef<String>).
323 ///
324 /// # Returns
325 ///
326 /// - `&mut Self` - A mutable reference to self for chaining.
327 #[inline]
328 pub fn remove_header_value<K, V>(&mut self, key: K, value: V) -> &mut Self
329 where
330 K: AsRef<str>,
331 V: AsRef<str>,
332 {
333 let key: ResponseHeadersKey = key.as_ref().to_lowercase();
334 if let Some(values) = self.headers.get_mut(&key) {
335 values.retain(|v| v != &value.as_ref().to_owned());
336 if values.is_empty() {
337 self.headers.remove(&key);
338 }
339 }
340 self
341 }
342
343 /// Clears all headers from the response.
344 ///
345 /// This function removes all headers, leaving the headers map empty.
346 ///
347 /// # Returns
348 ///
349 /// - `&mut Self` - A mutable reference to self for chaining.
350 #[inline]
351 pub fn clear_headers(&mut self) -> &mut Self {
352 self.headers.clear();
353 self
354 }
355
356 /// Sets the body of the response.
357 ///
358 /// This method allows you to set the body of the response by converting the provided
359 /// value as_ref a `ResponseBody` type. The `body` is updated with the converted value.
360 ///
361 /// # Arguments
362 ///
363 /// - `AsRef<[u8]>` - The body content (must implement AsRef<[u8]>).
364 ///
365 /// # Returns
366 ///
367 /// - `&mut Self` - A mutable reference to self for chaining.
368 #[inline]
369 pub fn set_body<T>(&mut self, body: T) -> &mut Self
370 where
371 T: AsRef<[u8]>,
372 {
373 self.body = body.as_ref().to_owned();
374 self
375 }
376
377 /// Sets the reason phrase of the response.
378 ///
379 /// This method allows you to set the reason phrase of the response by converting the
380 /// provided value as_ref a `ResponseReasonPhrase` type. The `reason_phrase` is updated
381 /// with the converted value.
382 ///
383 /// # Arguments
384 ///
385 /// - `AsRef<str>` - The reason phrase (must implement AsRef<str>).
386 ///
387 /// # Returns
388 ///
389 /// - `&mut Self` - A mutable reference to self for chaining.
390 #[inline]
391 pub fn set_reason_phrase<T>(&mut self, reason_phrase: T) -> &mut Self
392 where
393 T: AsRef<str>,
394 {
395 self.reason_phrase = reason_phrase.as_ref().to_owned();
396 self
397 }
398
399 /// Pushes a header with a key and value as_ref the response string.
400 ///
401 /// # Arguments
402 ///
403 /// - `&mut String`: A mutable reference to the string where the header will be added.
404 /// - `&str`: The header key as a string slice (`&str`).
405 /// - `&str`: The header value as a string slice (`&str`).
406 #[inline]
407 fn push_header(response_string: &mut String, key: &str, value: &str) {
408 response_string.push_str(key);
409 response_string.push_str(COLON_SPACE);
410 response_string.push_str(value);
411 response_string.push_str(HTTP_BR);
412 }
413
414 /// Pushes the first line of an HTTP response (version, status code, and reason phrase) as_ref the response string.
415 /// This corresponds to the status line of the HTTP response.
416 ///
417 /// # Arguments
418 ///
419 /// - `response_string`: A mutable reference to the string where the first line will be added.
420 #[inline]
421 fn push_http_first_line(&self, response_string: &mut String) {
422 response_string.push_str(&self.get_version().to_string());
423 response_string.push_str(SPACE);
424 response_string.push_str(&self.get_status_code().to_string());
425 response_string.push_str(SPACE);
426 response_string.push_str(self.get_reason_phrase());
427 response_string.push_str(HTTP_BR);
428 }
429
430 /// Builds the full HTTP response as a byte vector.
431 ///
432 /// This method constructs the complete HTTP response, including the status line,
433 /// headers, and body. It handles content encoding, content type, connection
434 /// management, and content length.
435 ///
436 /// # Returns
437 ///
438 /// - `ResponseData` - The complete HTTP response bytes.
439 pub fn build(&mut self) -> ResponseData {
440 if self.reason_phrase.is_empty() {
441 self.set_reason_phrase(HttpStatus::phrase(*self.get_status_code()));
442 }
443 let mut response_string: String = String::with_capacity(DEFAULT_BUFFER_SIZE);
444 self.push_http_first_line(&mut response_string);
445 let compress_type_opt: OptionCompress = self
446 .try_get_header_back(CONTENT_ENCODING)
447 .map(|value| value.parse::<Compress>().unwrap_or_default());
448 if self.try_get_header_back(CONNECTION).is_none() {
449 self.set_header_without_check(CONNECTION, KEEP_ALIVE);
450 }
451 let content_type: ResponseHeadersValueItem =
452 self.try_get_header_back(CONTENT_TYPE).unwrap_or_else(|| {
453 let mut content_type: String = String::with_capacity(
454 TEXT_HTML.len() + SEMICOLON_SPACE.len() + CHARSET_UTF_8.len(),
455 );
456 content_type.push_str(TEXT_HTML);
457 content_type.push_str(SEMICOLON_SPACE);
458 content_type.push_str(CHARSET_UTF_8);
459 self.set_header_without_check(CONTENT_TYPE, &content_type);
460 content_type
461 });
462 let mut body: ResponseBody = self.get_body().clone();
463 if let Some(compress_type) = compress_type_opt {
464 if !compress_type.is_unknown() {
465 body = compress_type
466 .encode(&body, DEFAULT_BUFFER_SIZE)
467 .into_owned();
468 }
469 }
470 if !content_type.eq_ignore_ascii_case(TEXT_EVENT_STREAM) {
471 self.set_header_without_check(CONTENT_LENGTH.to_owned(), body.len().to_string());
472 }
473 self.get_headers().iter().for_each(|(key, values)| {
474 for value in values.iter() {
475 Self::push_header(&mut response_string, key, value);
476 }
477 });
478 response_string.push_str(HTTP_BR);
479 let mut response_bytes: Vec<u8> = response_string.into_bytes();
480 response_bytes.extend_from_slice(&body);
481 response_bytes
482 }
483
484 /// Converts the response to a formatted string representation.
485 ///
486 /// This method provides a human-readable summary of the response, including its version,
487 /// status code, reason phrase, headers, and body information.
488 ///
489 /// # Returns
490 ///
491 /// A `String` containing formatted response details.
492 #[inline]
493 pub fn get_string(&self) -> String {
494 let body: &Vec<u8> = self.get_body();
495 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
496 PLAIN
497 } else {
498 BINARY
499 };
500 format!(
501 "[Response] => [version]: {}; [status code]: {}; [reason]: {}; [headers]: {:?}; [body]: {} bytes {};",
502 self.get_version(),
503 self.get_status_code(),
504 self.get_reason_phrase(),
505 self.get_headers(),
506 body.len(),
507 body_type
508 )
509 }
510}