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