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 pub fn new() -> Self {
27 Self::default()
28 }
29
30 /// Parses an HTTP request from a buffered TCP stream reader.
31 ///
32 /// Reads request line, headers and body from the stream and constructs a Request object.
33 ///
34 /// # Arguments
35 ///
36 /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
37 /// - `usize` - The buffer size for reading.
38 ///
39 /// # Returns
40 ///
41 /// - `Result<Request, RequestError>` - The parsed request or an error.
42 pub async fn http_from_reader(
43 reader: &mut BufReader<&mut TcpStream>,
44 buffer: usize,
45 ) -> RequestReaderHandleResult {
46 let mut request_line: String = String::with_capacity(buffer);
47 let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
48 let parts: Vec<&str> = request_line.split_whitespace().collect();
49 let parts_len: usize = parts.len();
50 if parts_len < 3 {
51 return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
52 }
53 let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
54 let full_path: RequestPath = parts[1].to_string();
55 let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
56 let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
57 let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
58 let query_string: String = query_index.map_or(String::new(), |i| {
59 let temp: &str = &full_path[i + 1..];
60 if hash_index.is_none() || hash_index.unwrap() <= i {
61 return temp.to_string();
62 }
63 temp.split(HASH_SYMBOL)
64 .next()
65 .unwrap_or_default()
66 .to_string()
67 });
68 let querys: RequestQuerys = Self::parse_querys(&query_string);
69 let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
70 full_path[..i].to_string()
71 } else {
72 full_path
73 };
74 let mut headers: RequestHeaders = hash_map_xx_hash3_64();
75 let mut host: RequestHost = String::new();
76 let mut content_length: usize = 0;
77 loop {
78 let mut header_line: String = String::with_capacity(buffer);
79 let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
80 let header_line: &str = header_line.trim();
81 if header_line.is_empty() {
82 break;
83 }
84 if let Some((key_part, value_part)) = header_line.split_once(COLON_SPACE_SYMBOL) {
85 let key: String = key_part.trim().to_ascii_lowercase();
86 if key.is_empty() {
87 continue;
88 }
89 let value: String = value_part.trim().to_string();
90 if key == HOST {
91 host = value.clone();
92 } else if key == CONTENT_LENGTH {
93 content_length = value.parse().unwrap_or(0);
94 }
95 headers
96 .entry(key)
97 .or_insert_with(VecDeque::new)
98 .push_back(value);
99 }
100 }
101 let mut body: RequestBody = vec![0; content_length];
102 if content_length > 0 {
103 let _ = AsyncReadExt::read_exact(reader, &mut body).await;
104 }
105 Ok(Request {
106 method,
107 host,
108 version,
109 path,
110 querys,
111 headers,
112 body,
113 })
114 }
115
116 /// Parses an HTTP request from a TCP stream.
117 ///
118 /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
119 ///
120 /// # Arguments
121 ///
122 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
123 /// - `usize` - The buffer size for reading.
124 ///
125 /// # Returns
126 ///
127 /// - `Result<Request, RequestError>` - The parsed request or an error.
128 pub async fn http_from_stream(
129 stream: &ArcRwLockStream,
130 buffer: usize,
131 ) -> RequestReaderHandleResult {
132 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
133 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
134 Self::http_from_reader(&mut reader, buffer).await
135 }
136
137 /// Parses a WebSocket request from a TCP stream.
138 ///
139 /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
140 ///
141 /// # Arguments
142 ///
143 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
144 /// - `usize` - The buffer size for reading.
145 /// - `&mut Request` - The request template to populate.
146 ///
147 /// # Returns
148 ///
149 /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
150 pub async fn ws_from_stream(
151 stream: &ArcRwLockStream,
152 buffer: usize,
153 request: &mut Self,
154 ) -> RequestReaderHandleResult {
155 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
156 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
157 Self::ws_from_reader(&mut reader, buffer, request).await
158 }
159
160 /// Parses a WebSocket request from a buffered TCP stream.
161 ///
162 /// Handles WebSocket frames including text, binary, ping, pong and close frames.
163 /// Assembles the request body from frame payload data.
164 ///
165 /// # Arguments
166 ///
167 /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
168 /// - `usize` - The buffer size for reading frames.
169 /// - `&mut Request` - The request template to populate.
170 ///
171 /// # Returns
172 ///
173 /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
174 pub async fn ws_from_reader(
175 reader: &mut BufReader<&mut TcpStream>,
176 buffer: usize,
177 request: &mut Self,
178 ) -> RequestReaderHandleResult {
179 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer);
180 let mut temp_buffer: Vec<u8> = vec![0; buffer];
181 let mut full_frame: Vec<u8> = Vec::new();
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 pub fn try_get_query<K>(&self, key: K) -> OptionRequestQuerysValue
272 where
273 K: AsRef<str>,
274 {
275 self.querys.get(key.as_ref()).cloned()
276 }
277
278 /// Retrieves the value of a request header by its key.
279 ///
280 /// # Arguments
281 ///
282 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
283 ///
284 /// # Returns
285 ///
286 /// - `OptionRequestHeadersValue` - The optional header values.
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 pub fn try_get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
304 where
305 K: AsRef<str>,
306 {
307 self.headers
308 .get(key.as_ref())
309 .and_then(|values| values.front().cloned())
310 }
311
312 /// Retrieves the last value of a request header by its key.
313 ///
314 /// # Arguments
315 ///
316 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
317 ///
318 /// # Returns
319 ///
320 /// - `OptionRequestHeadersValueItem` - The last header value if exists.
321 pub fn try_get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
322 where
323 K: AsRef<str>,
324 {
325 self.headers
326 .get(key.as_ref())
327 .and_then(|values| values.back().cloned())
328 }
329
330 /// Retrieves the number of values for a specific header.
331 ///
332 /// # Arguments
333 ///
334 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
335 ///
336 /// # Returns
337 ///
338 /// - `usize` - The count of values for the header.
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 pub fn get_headers_values_length(&self) -> usize {
355 self.headers.values().map(|values| values.len()).sum()
356 }
357
358 /// Retrieves the number of unique headers.
359 ///
360 /// # Returns
361 ///
362 /// - `usize` - The count of unique header keys.
363 pub fn get_headers_length(&self) -> usize {
364 self.headers.len()
365 }
366
367 /// Checks if a specific header exists.
368 ///
369 /// # Arguments
370 ///
371 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
372 ///
373 /// # Returns
374 ///
375 /// - `bool` - Whether the header exists.
376 pub fn has_header<K>(&self, key: K) -> bool
377 where
378 K: AsRef<str>,
379 {
380 self.headers.contains_key(key.as_ref())
381 }
382
383 /// Checks if a header contains a specific value.
384 ///
385 /// # Arguments
386 ///
387 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
388 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
389 ///
390 /// # Returns
391 ///
392 /// - `bool` - Whether the header contains the value.
393 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
394 where
395 K: AsRef<str>,
396 V: AsRef<str>,
397 {
398 if let Some(values) = self.headers.get(key.as_ref()) {
399 values.contains(&value.as_ref().to_owned())
400 } else {
401 false
402 }
403 }
404
405 /// Retrieves the body content of the request as a UTF-8 encoded string.
406 ///
407 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
408 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
409 ///
410 /// # Returns
411 ///
412 /// - `String` - The body content as a string.
413 pub fn get_body_string(&self) -> String {
414 String::from_utf8_lossy(self.get_body()).into_owned()
415 }
416
417 /// Deserializes the body content of the request as_ref a specified type `T`.
418 ///
419 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
420 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
421 ///
422 /// # Arguments
423 ///
424 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
425 ///
426 /// # Returns
427 ///
428 /// - `ResultJsonError<T>` - The deserialization result.
429 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
430 where
431 T: DeserializeOwned,
432 {
433 json_from_slice(self.get_body())
434 }
435
436 /// Converts the request to a formatted string representation.
437 ///
438 /// This method provides a human-readable summary of the request, including its method,
439 /// host, version, path, query parameters, headers, and body information.
440 ///
441 /// # Returns
442 ///
443 /// - `String` - The formatted request details.
444 pub fn get_string(&self) -> String {
445 let body: &Vec<u8> = self.get_body();
446 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
447 PLAIN
448 } else {
449 BINARY
450 };
451 format!(
452 "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
453 self.get_method(),
454 self.get_host(),
455 self.get_version(),
456 self.get_path(),
457 self.get_querys(),
458 self.get_headers(),
459 body.len(),
460 body_type
461 )
462 }
463
464 /// Retrieves the upgrade type from the request headers.
465 ///
466 /// This method looks for the `UPGRADE` header and attempts to parse its value
467 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
468 /// it returns the default `UpgradeType`.
469 ///
470 /// # Returns
471 ///
472 /// - `UpgradeType` - The parsed upgrade type.
473 pub fn get_upgrade_type(&self) -> UpgradeType {
474 let upgrade_type: UpgradeType = self
475 .try_get_header_back(UPGRADE)
476 .and_then(|data| data.parse::<UpgradeType>().ok())
477 .unwrap_or_default();
478 upgrade_type
479 }
480
481 /// Checks whether the WebSocket upgrade is enabled for this request.
482 ///
483 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
484 ///
485 /// # Returns
486 ///
487 /// - `bool` - Whether WebSocket upgrade is enabled.
488 pub fn is_ws(&self) -> bool {
489 self.get_upgrade_type().is_ws()
490 }
491
492 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
493 ///
494 /// # Returns
495 ///
496 /// - `bool` - Whether the upgrade type is h2c.
497 pub fn is_h2c(&self) -> bool {
498 self.get_upgrade_type().is_h2c()
499 }
500
501 /// Checks if the current upgrade type is TLS (any version).
502 ///
503 /// # Returns
504 ///
505 /// - `bool` - Whether the upgrade type is TLS.
506 pub fn is_tls(&self) -> bool {
507 self.get_upgrade_type().is_tls()
508 }
509
510 /// Checks whether the upgrade type is unknown.
511 ///
512 /// # Returns
513 ///
514 /// - `bool` - Whether the upgrade type is unknown.
515 pub fn is_unknown_upgrade(&self) -> bool {
516 self.get_upgrade_type().is_unknown()
517 }
518
519 /// Checks if the HTTP version is HTTP/1.1 or higher.
520 ///
521 /// # Returns
522 ///
523 /// - `bool` - Whether the version is HTTP/1.1 or higher.
524 pub fn is_http1_1_or_higher(&self) -> bool {
525 self.get_version().is_http1_1_or_higher()
526 }
527
528 /// Checks whether the HTTP version is HTTP/0.9.
529 ///
530 /// # Returns
531 ///
532 /// - `bool` - Whether the version is HTTP/0.9.
533 pub fn is_http0_9(&self) -> bool {
534 self.get_version().is_http0_9()
535 }
536
537 /// Checks whether the HTTP version is HTTP/1.0.
538 ///
539 /// # Returns
540 ///
541 /// - `bool` - Whether the version is HTTP/1.0.
542 pub fn is_http1_0(&self) -> bool {
543 self.get_version().is_http1_0()
544 }
545
546 /// Checks whether the HTTP version is HTTP/1.1.
547 ///
548 /// # Returns
549 ///
550 /// - `bool` - Whether the version is HTTP/1.1.
551 pub fn is_http1_1(&self) -> bool {
552 self.get_version().is_http1_1()
553 }
554
555 /// Checks whether the HTTP version is HTTP/2.
556 ///
557 /// # Returns
558 ///
559 /// - `bool` - Whether the version is HTTP/2.
560 pub fn is_http2(&self) -> bool {
561 self.get_version().is_http2()
562 }
563
564 /// Checks whether the HTTP version is HTTP/3.
565 ///
566 /// # Returns
567 ///
568 /// - `bool` - Whether the version is HTTP/3.
569 pub fn is_http3(&self) -> bool {
570 self.get_version().is_http3()
571 }
572
573 /// Checks whether the HTTP version is unknown.
574 ///
575 /// # Returns
576 ///
577 /// - `bool` - Whether the version is unknown.
578 pub fn is_unknown_version(&self) -> bool {
579 self.get_version().is_unknown()
580 }
581
582 /// Checks whether the version belongs to the HTTP family.
583 ///
584 /// # Returns
585 ///
586 /// - `bool` - Whether the version is HTTP.
587 pub fn is_http(&self) -> bool {
588 self.get_version().is_http()
589 }
590
591 /// Checks whether the request method is GET.
592 ///
593 /// # Returns
594 ///
595 /// - `bool` - Whether the method is GET.
596 pub fn is_get(&self) -> bool {
597 self.get_method().is_get()
598 }
599
600 /// Checks whether the request method is POST.
601 ///
602 /// # Returns
603 ///
604 /// - `bool` - Whether the method is POST.
605 pub fn is_post(&self) -> bool {
606 self.get_method().is_post()
607 }
608
609 /// Checks whether the request method is PUT.
610 ///
611 /// # Returns
612 ///
613 /// - `bool` - Whether the method is PUT.
614 pub fn is_put(&self) -> bool {
615 self.get_method().is_put()
616 }
617
618 /// Checks whether the request method is DELETE.
619 ///
620 /// # Returns
621 ///
622 /// - `bool` - Whether the method is DELETE.
623 pub fn is_delete(&self) -> bool {
624 self.get_method().is_delete()
625 }
626
627 /// Checks whether the request method is PATCH.
628 ///
629 /// # Returns
630 ///
631 /// - `bool` - Whether the method is PATCH.
632 pub fn is_patch(&self) -> bool {
633 self.get_method().is_patch()
634 }
635
636 /// Checks whether the request method is HEAD.
637 ///
638 /// # Returns
639 ///
640 /// - `bool` - Whether the method is HEAD.
641 pub fn is_head(&self) -> bool {
642 self.get_method().is_head()
643 }
644
645 /// Checks whether the request method is OPTIONS.
646 ///
647 /// # Returns
648 ///
649 /// - `bool` - Whether the method is OPTIONS.
650 pub fn is_options(&self) -> bool {
651 self.get_method().is_options()
652 }
653
654 /// Checks whether the request method is CONNECT.
655 ///
656 /// # Returns
657 ///
658 /// - `bool` - Whether the method is CONNECT.
659 pub fn is_connect(&self) -> bool {
660 self.get_method().is_connect()
661 }
662
663 /// Checks whether the request method is TRACE.
664 ///
665 /// # Returns
666 ///
667 /// - `bool` - Whether the method is TRACE.
668 pub fn is_trace(&self) -> bool {
669 self.get_method().is_trace()
670 }
671
672 /// Checks whether the request method is UNKNOWN.
673 ///
674 /// # Returns
675 ///
676 /// - `bool` - Whether the method is UNKNOWN.
677 pub fn is_unknown_method(&self) -> bool {
678 self.get_method().is_unknown()
679 }
680
681 /// Determines if a keep-alive connection should be enabled for this request.
682 ///
683 /// This function checks the `Connection` header and the HTTP version to determine
684 /// if keep-alive should be enabled. The logic is as follows:
685 ///
686 /// 1. If the `Connection` header exists:
687 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
688 /// - Returns `false` if the header value is "close" (case-insensitive).
689 /// 2. If no `Connection` header is present:
690 /// - Returns `true` if the HTTP version is 1.1 or higher.
691 /// - Returns `false` otherwise.
692 ///
693 /// # Returns
694 ///
695 /// - `bool` - Whether keep-alive should be enabled.
696 pub fn is_enable_keep_alive(&self) -> bool {
697 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
698 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
699 return true;
700 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
701 return self.is_ws();
702 }
703 }
704 self.is_http1_1_or_higher() || self.is_ws()
705 }
706
707 /// Determines if keep-alive should be disabled for this request.
708 ///
709 /// # Returns
710 ///
711 /// - `bool` - Whether keep-alive should be disabled.
712 pub fn is_disable_keep_alive(&self) -> bool {
713 !self.is_enable_keep_alive()
714 }
715}