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