http_type/request/impl.rs
1use crate::*;
2
3/// Provides a default value for `Request`.
4///
5/// Returns a new `Request` instance with all fields initialized to their default values.
6impl Default for Request {
7 fn default() -> Self {
8 Self {
9 method: Method::default(),
10 host: String::new(),
11 version: HttpVersion::default(),
12 path: String::new(),
13 querys: hash_map_xx_hash3_64(),
14 headers: hash_map_xx_hash3_64(),
15 body: Vec::new(),
16 }
17 }
18}
19
20impl Request {
21 /// Creates a new instance of `Request`.
22 ///
23 /// # Returns
24 ///
25 /// - `Request` - A new request instance with default values.
26 #[inline]
27 pub fn new() -> Self {
28 Self::default()
29 }
30
31 /// Parses an HTTP request from a buffered TCP stream reader.
32 ///
33 /// Reads request line, headers and body from the stream and constructs a Request object.
34 ///
35 /// # Arguments
36 ///
37 /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
38 /// - `usize` - The buffer size for reading.
39 ///
40 /// # Returns
41 ///
42 /// - `Result<Request, RequestError>` - The parsed request or an error.
43 pub async fn http_from_reader(
44 reader: &mut BufReader<&mut TcpStream>,
45 buffer: usize,
46 ) -> RequestReaderHandleResult {
47 let mut request_line: String = String::with_capacity(buffer);
48 let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
49 let parts: Vec<&str> = request_line.split_whitespace().collect();
50 let parts_len: usize = parts.len();
51 if parts_len < 3 {
52 return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
53 }
54 let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
55 let full_path: RequestPath = parts[1].to_string();
56 let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
57 let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
58 let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
59 let query_string: String = query_index.map_or(String::new(), |i| {
60 let temp: &str = &full_path[i + 1..];
61 if hash_index.is_none() || hash_index.unwrap() <= i {
62 return temp.to_string();
63 }
64 temp.split(HASH_SYMBOL)
65 .next()
66 .unwrap_or_default()
67 .to_string()
68 });
69 let querys: RequestQuerys = Self::parse_querys(&query_string);
70 let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
71 full_path[..i].to_string()
72 } else {
73 full_path
74 };
75 let mut headers: RequestHeaders = hash_map_xx_hash3_64();
76 let mut host: RequestHost = String::new();
77 let mut content_length: usize = 0;
78 loop {
79 let mut header_line: String = String::with_capacity(buffer);
80 let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
81 let header_line: &str = header_line.trim();
82 if header_line.is_empty() {
83 break;
84 }
85 if let Some((key_part, value_part)) = header_line.split_once(COLON_SPACE_SYMBOL) {
86 let key: String = key_part.trim().to_ascii_lowercase();
87 if key.is_empty() {
88 continue;
89 }
90 let value: String = value_part.trim().to_string();
91 if key == HOST {
92 host = value.clone();
93 } else if key == CONTENT_LENGTH {
94 content_length = value.parse().unwrap_or(0);
95 }
96 headers.entry(key).or_default().push_back(value);
97 }
98 }
99 let mut body: RequestBody = vec![0; content_length];
100 if content_length > 0 {
101 let _ = AsyncReadExt::read_exact(reader, &mut body).await;
102 }
103 Ok(Request {
104 method,
105 host,
106 version,
107 path,
108 querys,
109 headers,
110 body,
111 })
112 }
113
114 /// Parses an HTTP request from a TCP stream.
115 ///
116 /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
117 ///
118 /// # Arguments
119 ///
120 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
121 /// - `usize` - The buffer size for reading.
122 ///
123 /// # Returns
124 ///
125 /// - `Result<Request, RequestError>` - The parsed request or an error.
126 pub async fn http_from_stream(
127 stream: &ArcRwLockStream,
128 buffer: usize,
129 ) -> RequestReaderHandleResult {
130 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
131 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
132 Self::http_from_reader(&mut reader, buffer).await
133 }
134
135 /// Parses a WebSocket request from a TCP stream.
136 ///
137 /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
138 ///
139 /// # Arguments
140 ///
141 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
142 /// - `usize` - The buffer size for reading.
143 /// - `&mut Request` - The request template to populate.
144 ///
145 /// # Returns
146 ///
147 /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
148 pub async fn ws_from_stream(
149 stream: &ArcRwLockStream,
150 buffer: usize,
151 request: &mut Self,
152 ) -> RequestReaderHandleResult {
153 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
154 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
155 Self::ws_from_reader(&mut reader, buffer, request).await
156 }
157
158 /// Parses a WebSocket request from a buffered TCP stream.
159 ///
160 /// Handles WebSocket frames including text, binary, ping, pong and close frames.
161 /// Assembles the request body from frame payload data.
162 ///
163 /// # Arguments
164 ///
165 /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
166 /// - `usize` - The buffer size for reading frames.
167 /// - `&mut Request` - The request template to populate.
168 ///
169 /// # Returns
170 ///
171 /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
172 pub async fn ws_from_reader(
173 reader: &mut BufReader<&mut TcpStream>,
174 buffer: usize,
175 request: &mut Self,
176 ) -> RequestReaderHandleResult {
177 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer);
178 let mut temp_buffer: Vec<u8> = vec![0; buffer];
179 let mut full_frame: Vec<u8> = Vec::new();
180 let mut error_handle = || {
181 request.body.clear();
182 };
183 loop {
184 let len: usize = match reader.read(&mut temp_buffer).await {
185 Ok(len) => len,
186 Err(err) => {
187 error_handle();
188 if err.kind() == ErrorKind::ConnectionReset
189 || err.kind() == ErrorKind::ConnectionAborted
190 {
191 return Err(RequestError::ClientDisconnected);
192 }
193 return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
194 }
195 };
196 if len == 0 {
197 error_handle();
198 return Err(RequestError::IncompleteWebSocketFrame);
199 }
200 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
201 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
202 dynamic_buffer.drain(0..consumed);
203 match frame.get_opcode() {
204 WebSocketOpcode::Close => {
205 error_handle();
206 return Err(RequestError::ClientClosedConnection);
207 }
208 WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
209 continue;
210 }
211 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
212 full_frame.extend_from_slice(frame.get_payload_data());
213 if *frame.get_fin() {
214 let mut request: Request = request.clone();
215 request.body = full_frame;
216 return Ok(request);
217 }
218 }
219 _ => {
220 error_handle();
221 return Err(RequestError::InvalidWebSocketFrame(
222 "Unsupported opcode".to_owned(),
223 ));
224 }
225 }
226 }
227 }
228 }
229
230 /// Parses a query string as_ref key-value pairs.
231 ///
232 /// Expects format "key1=value1&key2=value2". Empty values are allowed.
233 ///
234 /// # Arguments
235 ///
236 /// - `&str` - The query string to parse.
237 ///
238 /// # Returns
239 ///
240 /// - `HashMap<String, String>` - The parsed query parameters.
241 fn parse_querys<Q>(query: Q) -> RequestQuerys
242 where
243 Q: AsRef<str>,
244 {
245 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
246 for pair in query.as_ref().split(AND) {
247 if let Some((key, value)) = pair.split_once(EQUAL) {
248 if !key.is_empty() {
249 query_map.insert(key.to_string(), value.to_string());
250 }
251 } else if !pair.is_empty() {
252 query_map.insert(pair.to_string(), String::new());
253 }
254 }
255 query_map
256 }
257
258 /// Gets a query parameter value by key.
259 ///
260 /// The key type must implement AsRef<str> conversion.
261 ///
262 /// # Arguments
263 ///
264 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
265 ///
266 /// # Returns
267 ///
268 /// - `Option<String>` - The parameter value if exists.
269 #[inline]
270 pub fn try_get_query<K>(&self, key: K) -> OptionRequestQuerysValue
271 where
272 K: AsRef<str>,
273 {
274 self.querys.get(key.as_ref()).cloned()
275 }
276
277 /// Retrieves the value of a request header by its key.
278 ///
279 /// # Arguments
280 ///
281 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
282 ///
283 /// # Returns
284 ///
285 /// - `OptionRequestHeadersValue` - The optional header values.
286 #[inline]
287 pub fn try_get_header<K>(&self, key: K) -> OptionRequestHeadersValue
288 where
289 K: AsRef<str>,
290 {
291 self.headers.get(key.as_ref()).cloned()
292 }
293
294 /// Retrieves the first value of a request header by its key.
295 ///
296 /// # Arguments
297 ///
298 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
299 ///
300 /// # Returns
301 ///
302 /// - `OptionRequestHeadersValueItem` - The first header value if exists.
303 #[inline]
304 pub fn try_get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
305 where
306 K: AsRef<str>,
307 {
308 self.headers
309 .get(key.as_ref())
310 .and_then(|values| values.front().cloned())
311 }
312
313 /// Retrieves the last value of a request header by its key.
314 ///
315 /// # Arguments
316 ///
317 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
318 ///
319 /// # Returns
320 ///
321 /// - `OptionRequestHeadersValueItem` - The last header value if exists.
322 #[inline]
323 pub fn try_get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
324 where
325 K: AsRef<str>,
326 {
327 self.headers
328 .get(key.as_ref())
329 .and_then(|values| values.back().cloned())
330 }
331
332 /// Retrieves the number of values for a specific header.
333 ///
334 /// # Arguments
335 ///
336 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
337 ///
338 /// # Returns
339 ///
340 /// - `usize` - The count of values for the header.
341 #[inline]
342 pub fn get_header_length<K>(&self, key: K) -> usize
343 where
344 K: AsRef<str>,
345 {
346 self.headers
347 .get(key.as_ref())
348 .map(|values| values.len())
349 .unwrap_or(0)
350 }
351
352 /// Retrieves the total number of header values across all headers.
353 ///
354 /// # Returns
355 ///
356 /// - `usize` - The total count of all header values.
357 #[inline]
358 pub fn get_headers_values_length(&self) -> usize {
359 self.headers.values().map(|values| values.len()).sum()
360 }
361
362 /// Retrieves the number of unique headers.
363 ///
364 /// # Returns
365 ///
366 /// - `usize` - The count of unique header keys.
367 #[inline]
368 pub fn get_headers_length(&self) -> usize {
369 self.headers.len()
370 }
371
372 /// Checks if a specific header exists.
373 ///
374 /// # Arguments
375 ///
376 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
377 ///
378 /// # Returns
379 ///
380 /// - `bool` - Whether the header exists.
381 #[inline]
382 pub fn has_header<K>(&self, key: K) -> bool
383 where
384 K: AsRef<str>,
385 {
386 self.headers.contains_key(key.as_ref())
387 }
388
389 /// Checks if a header contains a specific value.
390 ///
391 /// # Arguments
392 ///
393 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
394 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
395 ///
396 /// # Returns
397 ///
398 /// - `bool` - Whether the header contains the value.
399 #[inline]
400 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
401 where
402 K: AsRef<str>,
403 V: AsRef<str>,
404 {
405 if let Some(values) = self.headers.get(key.as_ref()) {
406 values.contains(&value.as_ref().to_owned())
407 } else {
408 false
409 }
410 }
411
412 /// Retrieves the body content of the request as a UTF-8 encoded string.
413 ///
414 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
415 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
416 ///
417 /// # Returns
418 ///
419 /// - `String` - The body content as a string.
420 #[inline]
421 pub fn get_body_string(&self) -> String {
422 String::from_utf8_lossy(self.get_body()).into_owned()
423 }
424
425 /// Deserializes the body content of the request as_ref a specified type `T`.
426 ///
427 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
428 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
429 ///
430 /// # Arguments
431 ///
432 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
433 ///
434 /// # Returns
435 ///
436 /// - `ResultJsonError<T>` - The deserialization result.
437 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
438 where
439 T: DeserializeOwned,
440 {
441 json_from_slice(self.get_body())
442 }
443
444 /// Converts the request to a formatted string representation.
445 ///
446 /// This method provides a human-readable summary of the request, including its method,
447 /// host, version, path, query parameters, headers, and body information.
448 ///
449 /// # Returns
450 ///
451 /// - `String` - The formatted request details.
452 #[inline]
453 pub fn get_string(&self) -> String {
454 let body: &Vec<u8> = self.get_body();
455 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
456 PLAIN
457 } else {
458 BINARY
459 };
460 format!(
461 "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
462 self.get_method(),
463 self.get_host(),
464 self.get_version(),
465 self.get_path(),
466 self.get_querys(),
467 self.get_headers(),
468 body.len(),
469 body_type
470 )
471 }
472
473 /// Retrieves the upgrade type from the request headers.
474 ///
475 /// This method looks for the `UPGRADE` header and attempts to parse its value
476 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
477 /// it returns the default `UpgradeType`.
478 ///
479 /// # Returns
480 ///
481 /// - `UpgradeType` - The parsed upgrade type.
482 #[inline]
483 pub fn get_upgrade_type(&self) -> UpgradeType {
484 let upgrade_type: UpgradeType = self
485 .try_get_header_back(UPGRADE)
486 .and_then(|data| data.parse::<UpgradeType>().ok())
487 .unwrap_or_default();
488 upgrade_type
489 }
490
491 /// Checks whether the WebSocket upgrade is enabled for this request.
492 ///
493 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
494 ///
495 /// # Returns
496 ///
497 /// - `bool` - Whether WebSocket upgrade is enabled.
498 #[inline]
499 pub fn is_ws(&self) -> bool {
500 self.get_upgrade_type().is_ws()
501 }
502
503 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
504 ///
505 /// # Returns
506 ///
507 /// - `bool` - Whether the upgrade type is h2c.
508 #[inline]
509 pub fn is_h2c(&self) -> bool {
510 self.get_upgrade_type().is_h2c()
511 }
512
513 /// Checks if the current upgrade type is TLS (any version).
514 ///
515 /// # Returns
516 ///
517 /// - `bool` - Whether the upgrade type is TLS.
518 #[inline]
519 pub fn is_tls(&self) -> bool {
520 self.get_upgrade_type().is_tls()
521 }
522
523 /// Checks whether the upgrade type is unknown.
524 ///
525 /// # Returns
526 ///
527 /// - `bool` - Whether the upgrade type is unknown.
528 #[inline]
529 pub fn is_unknown_upgrade(&self) -> bool {
530 self.get_upgrade_type().is_unknown()
531 }
532
533 /// Checks if the HTTP version is HTTP/1.1 or higher.
534 ///
535 /// # Returns
536 ///
537 /// - `bool` - Whether the version is HTTP/1.1 or higher.
538 #[inline]
539 pub fn is_http1_1_or_higher(&self) -> bool {
540 self.get_version().is_http1_1_or_higher()
541 }
542
543 /// Checks whether the HTTP version is HTTP/0.9.
544 ///
545 /// # Returns
546 ///
547 /// - `bool` - Whether the version is HTTP/0.9.
548 #[inline]
549 pub fn is_http0_9(&self) -> bool {
550 self.get_version().is_http0_9()
551 }
552
553 /// Checks whether the HTTP version is HTTP/1.0.
554 ///
555 /// # Returns
556 ///
557 /// - `bool` - Whether the version is HTTP/1.0.
558 #[inline]
559 pub fn is_http1_0(&self) -> bool {
560 self.get_version().is_http1_0()
561 }
562
563 /// Checks whether the HTTP version is HTTP/1.1.
564 ///
565 /// # Returns
566 ///
567 /// - `bool` - Whether the version is HTTP/1.1.
568 #[inline]
569 pub fn is_http1_1(&self) -> bool {
570 self.get_version().is_http1_1()
571 }
572
573 /// Checks whether the HTTP version is HTTP/2.
574 ///
575 /// # Returns
576 ///
577 /// - `bool` - Whether the version is HTTP/2.
578 #[inline]
579 pub fn is_http2(&self) -> bool {
580 self.get_version().is_http2()
581 }
582
583 /// Checks whether the HTTP version is HTTP/3.
584 ///
585 /// # Returns
586 ///
587 /// - `bool` - Whether the version is HTTP/3.
588 #[inline]
589 pub fn is_http3(&self) -> bool {
590 self.get_version().is_http3()
591 }
592
593 /// Checks whether the HTTP version is unknown.
594 ///
595 /// # Returns
596 ///
597 /// - `bool` - Whether the version is unknown.
598 #[inline]
599 pub fn is_unknown_version(&self) -> bool {
600 self.get_version().is_unknown()
601 }
602
603 /// Checks whether the version belongs to the HTTP family.
604 ///
605 /// # Returns
606 ///
607 /// - `bool` - Whether the version is HTTP.
608 #[inline]
609 pub fn is_http(&self) -> bool {
610 self.get_version().is_http()
611 }
612
613 /// Checks whether the request method is GET.
614 ///
615 /// # Returns
616 ///
617 /// - `bool` - Whether the method is GET.
618 #[inline]
619 pub fn is_get(&self) -> bool {
620 self.get_method().is_get()
621 }
622
623 /// Checks whether the request method is POST.
624 ///
625 /// # Returns
626 ///
627 /// - `bool` - Whether the method is POST.
628 #[inline]
629 pub fn is_post(&self) -> bool {
630 self.get_method().is_post()
631 }
632
633 /// Checks whether the request method is PUT.
634 ///
635 /// # Returns
636 ///
637 /// - `bool` - Whether the method is PUT.
638 #[inline]
639 pub fn is_put(&self) -> bool {
640 self.get_method().is_put()
641 }
642
643 /// Checks whether the request method is DELETE.
644 ///
645 /// # Returns
646 ///
647 /// - `bool` - Whether the method is DELETE.
648 #[inline]
649 pub fn is_delete(&self) -> bool {
650 self.get_method().is_delete()
651 }
652
653 /// Checks whether the request method is PATCH.
654 ///
655 /// # Returns
656 ///
657 /// - `bool` - Whether the method is PATCH.
658 #[inline]
659 pub fn is_patch(&self) -> bool {
660 self.get_method().is_patch()
661 }
662
663 /// Checks whether the request method is HEAD.
664 ///
665 /// # Returns
666 ///
667 /// - `bool` - Whether the method is HEAD.
668 #[inline]
669 pub fn is_head(&self) -> bool {
670 self.get_method().is_head()
671 }
672
673 /// Checks whether the request method is OPTIONS.
674 ///
675 /// # Returns
676 ///
677 /// - `bool` - Whether the method is OPTIONS.
678 #[inline]
679 pub fn is_options(&self) -> bool {
680 self.get_method().is_options()
681 }
682
683 /// Checks whether the request method is CONNECT.
684 ///
685 /// # Returns
686 ///
687 /// - `bool` - Whether the method is CONNECT.
688 #[inline]
689 pub fn is_connect(&self) -> bool {
690 self.get_method().is_connect()
691 }
692
693 /// Checks whether the request method is TRACE.
694 ///
695 /// # Returns
696 ///
697 /// - `bool` - Whether the method is TRACE.
698 #[inline]
699 pub fn is_trace(&self) -> bool {
700 self.get_method().is_trace()
701 }
702
703 /// Checks whether the request method is UNKNOWN.
704 ///
705 /// # Returns
706 ///
707 /// - `bool` - Whether the method is UNKNOWN.
708 #[inline]
709 pub fn is_unknown_method(&self) -> bool {
710 self.get_method().is_unknown()
711 }
712
713 /// Determines if a keep-alive connection should be enabled for this request.
714 ///
715 /// This function checks the `Connection` header and the HTTP version to determine
716 /// if keep-alive should be enabled. The logic is as follows:
717 ///
718 /// 1. If the `Connection` header exists:
719 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
720 /// - Returns `false` if the header value is "close" (case-insensitive).
721 /// 2. If no `Connection` header is present:
722 /// - Returns `true` if the HTTP version is 1.1 or higher.
723 /// - Returns `false` otherwise.
724 ///
725 /// # Returns
726 ///
727 /// - `bool` - Whether keep-alive should be enabled.
728 #[inline]
729 pub fn is_enable_keep_alive(&self) -> bool {
730 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
731 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
732 return true;
733 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
734 return self.is_ws();
735 }
736 }
737 self.is_http1_1_or_higher() || self.is_ws()
738 }
739
740 /// Determines if keep-alive should be disabled for this request.
741 ///
742 /// # Returns
743 ///
744 /// - `bool` - Whether keep-alive should be disabled.
745 #[inline]
746 pub fn is_disable_keep_alive(&self) -> bool {
747 !self.is_enable_keep_alive()
748 }
749}