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