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