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