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_size: usize,
45 ) -> RequestReaderHandleResult {
46 let mut request_line: String = String::with_capacity(buffer_size);
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_size);
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_size: 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_size).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_size: 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_size, 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_size: usize,
177 request: &mut Self,
178 ) -> RequestReaderHandleResult {
179 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
180 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
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".into(),
225 ));
226 }
227 }
228 }
229 }
230 }
231
232 /// Parses a query string into 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(query: &str) -> RequestQuerys {
244 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
245 for pair in query.split(AND) {
246 if let Some((key, value)) = pair.split_once(EQUAL) {
247 if !key.is_empty() {
248 query_map.insert(key.to_string(), value.to_string());
249 }
250 } else if !pair.is_empty() {
251 query_map.insert(pair.to_string(), String::new());
252 }
253 }
254 query_map
255 }
256
257 /// Gets a query parameter value by key.
258 ///
259 /// The key type must implement Into<String> conversion.
260 ///
261 /// # Arguments
262 ///
263 /// - `K` - The query parameter key (implements Into<String>).
264 ///
265 /// # Returns
266 ///
267 /// - `Option<String>` - The parameter value if exists.
268 pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
269 where
270 K: Into<RequestQuerysKey>,
271 {
272 self.querys.get(&key.into()).cloned()
273 }
274
275 /// Retrieves the value of a request header by its key.
276 ///
277 /// # Arguments
278 ///
279 /// - `K` - The header's key (must implement Into<RequestHeadersKey>).
280 ///
281 /// # Returns
282 ///
283 /// - `OptionRequestHeadersValue` - The optional header values.
284 pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
285 where
286 K: Into<RequestHeadersKey>,
287 {
288 self.headers.get(&key.into()).cloned()
289 }
290
291 /// Retrieves the first value of a request header by its key.
292 ///
293 /// # Arguments
294 ///
295 /// - `K` - The header's key (must implement Into<RequestHeadersKey>).
296 ///
297 /// # Returns
298 ///
299 /// - `OptionRequestHeadersValueItem` - The first header value if exists.
300 pub fn get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
301 where
302 K: Into<RequestHeadersKey>,
303 {
304 self.headers
305 .get(&key.into())
306 .and_then(|values| values.front().cloned())
307 }
308
309 /// Retrieves the last value of a request header by its key.
310 ///
311 /// # Arguments
312 ///
313 /// - `K` - The header's key (must implement Into<RequestHeadersKey>).
314 ///
315 /// # Returns
316 ///
317 /// - `OptionRequestHeadersValueItem` - The last header value if exists.
318 pub fn get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
319 where
320 K: Into<RequestHeadersKey>,
321 {
322 self.headers
323 .get(&key.into())
324 .and_then(|values| values.back().cloned())
325 }
326
327 /// Retrieves the number of values for a specific header.
328 ///
329 /// # Arguments
330 ///
331 /// - `K` - The header's key (must implement Into<RequestHeadersKey>).
332 ///
333 /// # Returns
334 ///
335 /// - `usize` - The count of values for the header.
336 pub fn get_header_length<K>(&self, key: K) -> usize
337 where
338 K: Into<RequestHeadersKey>,
339 {
340 self.headers
341 .get(&key.into())
342 .map(|values| values.len())
343 .unwrap_or(0)
344 }
345
346 /// Retrieves the total number of header values across all headers.
347 ///
348 /// # Returns
349 ///
350 /// - `usize` - The total count of all header values.
351 pub fn get_headers_values_length(&self) -> usize {
352 self.headers.values().map(|values| values.len()).sum()
353 }
354
355 /// Retrieves the number of unique headers.
356 ///
357 /// # Returns
358 ///
359 /// - `usize` - The count of unique header keys.
360 pub fn get_headers_length(&self) -> usize {
361 self.headers.len()
362 }
363
364 /// Checks if a specific header exists.
365 ///
366 /// # Arguments
367 ///
368 /// - `K` - The header key to check (must implement Into<RequestHeadersKey>).
369 ///
370 /// # Returns
371 ///
372 /// - `bool` - Whether the header exists.
373 pub fn has_header<K>(&self, key: K) -> bool
374 where
375 K: Into<RequestHeadersKey>,
376 {
377 self.headers.contains_key(&key.into())
378 }
379
380 /// Checks if a header contains a specific value.
381 ///
382 /// # Arguments
383 ///
384 /// - `K` - The header key to check (must implement Into<RequestHeadersKey>).
385 /// - `V` - The value to search for (must implement Into<RequestHeadersValueItem>).
386 ///
387 /// # Returns
388 ///
389 /// - `bool` - Whether the header contains the value.
390 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
391 where
392 K: Into<RequestHeadersKey>,
393 V: Into<RequestHeadersValueItem>,
394 {
395 let key: RequestHeadersKey = key.into();
396 let value: RequestHeadersValueItem = value.into();
397 if let Some(values) = self.headers.get(&key) {
398 values.contains(&value)
399 } else {
400 false
401 }
402 }
403
404 /// Retrieves the body content of the request as a UTF-8 encoded string.
405 ///
406 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
407 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
408 ///
409 /// # Returns
410 ///
411 /// - `String` - The body content as a string.
412 pub fn get_body_string(&self) -> String {
413 String::from_utf8_lossy(self.get_body()).into_owned()
414 }
415
416 /// Deserializes the body content of the request into a specified type `T`.
417 ///
418 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
419 /// It then attempts to deserialize the byte slice into the specified type `T` using `json_from_slice`.
420 ///
421 /// # Type Parameters
422 ///
423 /// - `T` - The target type to deserialize into (must implement DeserializeOwned).
424 ///
425 /// # Returns
426 ///
427 /// - `ResultJsonError<T>` - The deserialization result.
428 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
429 where
430 T: DeserializeOwned,
431 {
432 json_from_slice(self.get_body())
433 }
434
435 /// Converts the request to a formatted string representation.
436 ///
437 /// This method provides a human-readable summary of the request, including its method,
438 /// host, version, path, query parameters, headers, and body information.
439 ///
440 /// # Returns
441 ///
442 /// - `String` - The formatted request details.
443 pub fn get_string(&self) -> String {
444 let body: &Vec<u8> = self.get_body();
445 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
446 PLAIN
447 } else {
448 BINARY
449 };
450 format!(
451 "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
452 self.get_method(),
453 self.get_host(),
454 self.get_version(),
455 self.get_path(),
456 self.get_querys(),
457 self.get_headers(),
458 body.len(),
459 body_type
460 )
461 }
462
463 /// Retrieves the upgrade type from the request headers.
464 ///
465 /// This method looks for the `UPGRADE` header and attempts to parse its value
466 /// into an `UpgradeType`. If the header is missing or the value is invalid,
467 /// it returns the default `UpgradeType`.
468 ///
469 /// # Returns
470 ///
471 /// - `UpgradeType` - The parsed upgrade type.
472 pub fn get_upgrade_type(&self) -> UpgradeType {
473 let upgrade_type: UpgradeType = self
474 .get_header_back(UPGRADE)
475 .and_then(|data| data.parse::<UpgradeType>().ok())
476 .unwrap_or_default();
477 upgrade_type
478 }
479
480 /// Checks whether the WebSocket upgrade is enabled for this request.
481 ///
482 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
483 ///
484 /// # Returns
485 ///
486 /// - `bool` - Whether WebSocket upgrade is enabled.
487 pub fn is_ws(&self) -> bool {
488 self.get_upgrade_type().is_ws()
489 }
490
491 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
492 ///
493 /// # Returns
494 ///
495 /// - `bool` - Whether the upgrade type is h2c.
496 pub fn is_h2c(&self) -> bool {
497 self.get_upgrade_type().is_h2c()
498 }
499
500 /// Checks if the current upgrade type is TLS (any version).
501 ///
502 /// # Returns
503 ///
504 /// - `bool` - Whether the upgrade type is TLS.
505 pub fn is_tls(&self) -> bool {
506 self.get_upgrade_type().is_tls()
507 }
508
509 /// Checks whether the upgrade type is unknown.
510 ///
511 /// # Returns
512 ///
513 /// - `bool` - Whether the upgrade type is unknown.
514 pub fn is_unknown_upgrade(&self) -> bool {
515 self.get_upgrade_type().is_unknown()
516 }
517
518 /// Checks if the HTTP version is HTTP/1.1 or higher.
519 ///
520 /// # Returns
521 ///
522 /// - `bool` - Whether the version is HTTP/1.1 or higher.
523 pub fn is_http1_1_or_higher(&self) -> bool {
524 self.get_version().is_http1_1_or_higher()
525 }
526
527 /// Checks whether the HTTP version is HTTP/0.9.
528 ///
529 /// # Returns
530 ///
531 /// - `bool` - Whether the version is HTTP/0.9.
532 pub fn is_http0_9(&self) -> bool {
533 self.get_version().is_http0_9()
534 }
535
536 /// Checks whether the HTTP version is HTTP/1.0.
537 ///
538 /// # Returns
539 ///
540 /// - `bool` - Whether the version is HTTP/1.0.
541 pub fn is_http1_0(&self) -> bool {
542 self.get_version().is_http1_0()
543 }
544
545 /// Checks whether the HTTP version is HTTP/1.1.
546 ///
547 /// # Returns
548 ///
549 /// - `bool` - Whether the version is HTTP/1.1.
550 pub fn is_http1_1(&self) -> bool {
551 self.get_version().is_http1_1()
552 }
553
554 /// Checks whether the HTTP version is HTTP/2.
555 ///
556 /// # Returns
557 ///
558 /// - `bool` - Whether the version is HTTP/2.
559 pub fn is_http2(&self) -> bool {
560 self.get_version().is_http2()
561 }
562
563 /// Checks whether the HTTP version is HTTP/3.
564 ///
565 /// # Returns
566 ///
567 /// - `bool` - Whether the version is HTTP/3.
568 pub fn is_http3(&self) -> bool {
569 self.get_version().is_http3()
570 }
571
572 /// Checks whether the HTTP version is unknown.
573 ///
574 /// # Returns
575 ///
576 /// - `bool` - Whether the version is unknown.
577 pub fn is_unknown_version(&self) -> bool {
578 self.get_version().is_unknown()
579 }
580
581 /// Checks whether the version belongs to the HTTP family.
582 ///
583 /// # Returns
584 ///
585 /// - `bool` - Whether the version is HTTP.
586 pub fn is_http(&self) -> bool {
587 self.get_version().is_http()
588 }
589
590 /// Checks whether the request method is GET.
591 ///
592 /// # Returns
593 ///
594 /// - `bool` - Whether the method is GET.
595 pub fn is_get(&self) -> bool {
596 self.get_method().is_get()
597 }
598
599 /// Checks whether the request method is POST.
600 ///
601 /// # Returns
602 ///
603 /// - `bool` - Whether the method is POST.
604 pub fn is_post(&self) -> bool {
605 self.get_method().is_post()
606 }
607
608 /// Checks whether the request method is PUT.
609 ///
610 /// # Returns
611 ///
612 /// - `bool` - Whether the method is PUT.
613 pub fn is_put(&self) -> bool {
614 self.get_method().is_put()
615 }
616
617 /// Checks whether the request method is DELETE.
618 ///
619 /// # Returns
620 ///
621 /// - `bool` - Whether the method is DELETE.
622 pub fn is_delete(&self) -> bool {
623 self.get_method().is_delete()
624 }
625
626 /// Checks whether the request method is PATCH.
627 ///
628 /// # Returns
629 ///
630 /// - `bool` - Whether the method is PATCH.
631 pub fn is_patch(&self) -> bool {
632 self.get_method().is_patch()
633 }
634
635 /// Checks whether the request method is HEAD.
636 ///
637 /// # Returns
638 ///
639 /// - `bool` - Whether the method is HEAD.
640 pub fn is_head(&self) -> bool {
641 self.get_method().is_head()
642 }
643
644 /// Checks whether the request method is OPTIONS.
645 ///
646 /// # Returns
647 ///
648 /// - `bool` - Whether the method is OPTIONS.
649 pub fn is_options(&self) -> bool {
650 self.get_method().is_options()
651 }
652
653 /// Checks whether the request method is CONNECT.
654 ///
655 /// # Returns
656 ///
657 /// - `bool` - Whether the method is CONNECT.
658 pub fn is_connect(&self) -> bool {
659 self.get_method().is_connect()
660 }
661
662 /// Checks whether the request method is TRACE.
663 ///
664 /// # Returns
665 ///
666 /// - `bool` - Whether the method is TRACE.
667 pub fn is_trace(&self) -> bool {
668 self.get_method().is_trace()
669 }
670
671 /// Checks whether the request method is UNKNOWN.
672 ///
673 /// # Returns
674 ///
675 /// - `bool` - Whether the method is UNKNOWN.
676 pub fn is_unknown_method(&self) -> bool {
677 self.get_method().is_unknown()
678 }
679
680 /// Determines if a keep-alive connection should be enabled for this request.
681 ///
682 /// This function checks the `Connection` header and the HTTP version to determine
683 /// if keep-alive should be enabled. The logic is as follows:
684 ///
685 /// 1. If the `Connection` header exists:
686 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
687 /// - Returns `false` if the header value is "close" (case-insensitive).
688 /// 2. If no `Connection` header is present:
689 /// - Returns `true` if the HTTP version is 1.1 or higher.
690 /// - Returns `false` otherwise.
691 ///
692 /// # Returns
693 ///
694 /// - `bool` - Whether keep-alive should be enabled.
695 pub fn is_enable_keep_alive(&self) -> bool {
696 if let Some(connection_value) = self.get_header_back(CONNECTION) {
697 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
698 return true;
699 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
700 return self.is_ws();
701 }
702 }
703 self.is_http1_1_or_higher() || self.is_ws()
704 }
705}