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