http_type/request/impl.rs
1use crate::*;
2
3/// Implements the `std::error::Error` trait for `RequestError`.
4impl std::error::Error for RequestError {}
5
6/// Provides a default value for `RequestError`.
7impl Default for RequestError {
8 /// Provides a default value for `RequestError`.
9 ///
10 /// Returns a `RequestError::Unknown` with `HttpStatus::InternalServerError`.
11 #[inline(always)]
12 fn default() -> Self {
13 RequestError::Unknown(HttpStatus::InternalServerError)
14 }
15}
16
17/// Converts an I/O error to a `RequestError`.
18///
19/// Maps connection reset and aborted errors to `ClientDisconnected`,
20/// all other I/O errors are mapped to `ReadConnection`.
21impl From<std::io::Error> for RequestError {
22 /// Converts an I/O error to a `RequestError`.
23 ///
24 /// # Arguments
25 ///
26 /// - `std::io::Error`: The I/O error to convert.
27 ///
28 /// # Returns
29 ///
30 /// - `RequestError`: The corresponding request error.
31 #[inline(always)]
32 fn from(error: std::io::Error) -> Self {
33 let kind: ErrorKind = error.kind();
34 if kind == ErrorKind::ConnectionReset || kind == ErrorKind::ConnectionAborted {
35 return RequestError::ClientDisconnected(HttpStatus::BadRequest);
36 }
37 RequestError::ReadConnection(HttpStatus::BadRequest)
38 }
39}
40
41/// Converts a timeout elapsed error to a `RequestError`.
42///
43/// Maps timeout errors to `ReadTimeout` with `HttpStatus::RequestTimeout`.
44impl From<Elapsed> for RequestError {
45 /// Converts a timeout elapsed error to a `RequestError`.
46 ///
47 /// # Arguments
48 ///
49 /// - `Elapsed`: The elapsed error to convert.
50 ///
51 /// # Returns
52 ///
53 /// - `RequestError`: The corresponding request error as `ReadTimeout`.
54 #[inline(always)]
55 fn from(_: Elapsed) -> Self {
56 RequestError::ReadTimeout(HttpStatus::RequestTimeout)
57 }
58}
59
60/// Converts a parse int error to a `RequestError`.
61///
62/// Maps parse int errors to `InvalidContentLength` with `HttpStatus::BadRequest`.
63impl From<ParseIntError> for RequestError {
64 /// Converts a parse int error to a `RequestError`.
65 ///
66 /// # Arguments
67 ///
68 /// - `ParseIntError`: The parse error to convert.
69 ///
70 /// # Returns
71 ///
72 /// - `RequestError`: The corresponding request error as `InvalidContentLength`.
73 #[inline(always)]
74 fn from(_: ParseIntError) -> Self {
75 RequestError::InvalidContentLength(HttpStatus::BadRequest)
76 }
77}
78
79/// Converts a response error to a `RequestError`.
80///
81/// Maps response errors to `WriteTimeout` with `HttpStatus::InternalServerError`.
82impl From<ResponseError> for RequestError {
83 /// Converts a response error to a `RequestError`.
84 ///
85 /// # Arguments
86 ///
87 /// - `ResponseError`: The response error to convert.
88 ///
89 /// # Returns
90 ///
91 /// - `RequestError`: The corresponding request error as `WriteTimeout`.
92 #[inline(always)]
93 fn from(_: ResponseError) -> Self {
94 RequestError::WriteTimeout(HttpStatus::InternalServerError)
95 }
96}
97
98impl RequestError {
99 /// Gets the HTTP status associated with this error.
100 ///
101 /// Returns the HttpStatus enum variant that corresponds to this error.
102 ///
103 /// # Returns
104 ///
105 /// - `HttpStatus` - The HTTP status associated with this error.
106 pub fn get_http_status(&self) -> HttpStatus {
107 match self {
108 Self::HttpRead(status) => *status,
109 Self::GetTcpStream(status) => *status,
110 Self::GetTlsStream(status) => *status,
111 Self::ReadConnection(status) => *status,
112 Self::RequestAborted(status) => *status,
113 Self::TlsStreamConnect(status) => *status,
114 Self::NeedOpenRedirect(status) => *status,
115 Self::MaxRedirectTimes(status) => *status,
116 Self::MethodsNotSupport(status) => *status,
117 Self::RedirectInvalidUrl(status) => *status,
118 Self::ClientDisconnected(status) => *status,
119 Self::RedirectUrlDeadLoop(status) => *status,
120 Self::ClientClosedConnection(status) => *status,
121 Self::IncompleteWebSocketFrame(status) => *status,
122 Self::RequestTooLong(status) => *status,
123 Self::PathTooLong(status) => *status,
124 Self::QueryTooLong(status) => *status,
125 Self::HeaderLineTooLong(status) => *status,
126 Self::TooManyHeaders(status) => *status,
127 Self::HeaderKeyTooLong(status) => *status,
128 Self::HeaderValueTooLong(status) => *status,
129 Self::ContentLengthTooLarge(status) => *status,
130 Self::InvalidContentLength(status) => *status,
131 Self::InvalidUrlScheme(status) => *status,
132 Self::InvalidUrlHost(status) => *status,
133 Self::InvalidUrlPort(status) => *status,
134 Self::InvalidUrlPath(status) => *status,
135 Self::InvalidUrlQuery(status) => *status,
136 Self::InvalidUrlFragment(status) => *status,
137 Self::ReadTimeout(status) => *status,
138 Self::WriteTimeout(status) => *status,
139 Self::TcpConnectionFailed(status) => *status,
140 Self::TlsHandshakeFailed(status) => *status,
141 Self::TlsCertificateInvalid(status) => *status,
142 Self::WebSocketFrameTooLarge(status) => *status,
143 Self::WebSocketOpcodeUnsupported(status) => *status,
144 Self::WebSocketMaskMissing(status) => *status,
145 Self::WebSocketPayloadCorrupted(status) => *status,
146 Self::WebSocketInvalidUtf8(status) => *status,
147 Self::WebSocketInvalidCloseCode(status) => *status,
148 Self::WebSocketInvalidExtension(status) => *status,
149 Self::HttpRequestPartsInsufficient(status) => *status,
150 Self::TcpStreamConnect(status) => *status,
151 Self::TlsConnectorBuild(status) => *status,
152 Self::InvalidUrl(status) => *status,
153 Self::ConfigReadError(status) => *status,
154 Self::TcpStreamConnectString(status) => *status,
155 Self::TlsConnectorBuildString(status) => *status,
156 Self::Request(_) => HttpStatus::BadRequest,
157 Self::Unknown(status) => *status,
158 }
159 }
160
161 /// Gets the numeric HTTP status code associated with this error.
162 ///
163 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
164 ///
165 /// # Returns
166 ///
167 /// - `ResponseStatusCode` - The numeric HTTP status code.
168 pub fn get_http_status_code(&self) -> ResponseStatusCode {
169 self.get_http_status().code()
170 }
171}
172
173impl Default for RequestConfigData {
174 /// Creates a `RequestConfig` with secure default values.
175 ///
176 /// # Returns
177 ///
178 /// - `RequestConfigData ` - A new config instance with secure defaults.
179 #[inline(always)]
180 fn default() -> Self {
181 Self {
182 buffer_size: DEFAULT_BUFFER_SIZE,
183 max_request_line_size: DEFAULT_MAX_REQUEST_LINE_SIZE,
184 max_path_size: DEFAULT_MAX_PATH_SIZE,
185 max_query_size: DEFAULT_MAX_QUERY_SIZE,
186 max_header_line_size: DEFAULT_MAX_HEADER_LINE_SIZE,
187 max_header_count: DEFAULT_MAX_HEADER_COUNT,
188 max_header_key_size: DEFAULT_MAX_HEADER_KEY_SIZE,
189 max_header_value_size: DEFAULT_MAX_HEADER_VALUE_SIZE,
190 max_body_size: DEFAULT_MAX_BODY_SIZE,
191 max_ws_frame_size: DEFAULT_MAX_WS_FRAME_SIZE,
192 max_ws_frames_count: DEFAULT_MAX_WS_FRAMES_COUNT,
193 http_read_timeout_ms: DEFAULT_HTTP_READ_TIMEOUT_MS,
194 ws_read_timeout_ms: DEFAULT_WS_READ_TIMEOUT_MS,
195 }
196 }
197}
198
199impl RequestConfigData {
200 /// Creates a config optimized for low-security environments.
201 ///
202 /// This configuration uses less restrictive limits to provide
203 /// basic protection against common attacks.
204 ///
205 /// # Returns
206 ///
207 /// - `RequestConfigData ` - A new config with low-security settings.
208 #[inline(always)]
209 pub(super) fn low_security() -> Self {
210 Self {
211 buffer_size: DEFAULT_LOW_SECURITY_BUFFER_SIZE,
212 max_request_line_size: DEFAULT_LOW_SECURITY_MAX_REQUEST_LINE_SIZE,
213 max_path_size: DEFAULT_LOW_SECURITY_MAX_PATH_SIZE,
214 max_query_size: DEFAULT_LOW_SECURITY_MAX_QUERY_SIZE,
215 max_header_line_size: DEFAULT_LOW_SECURITY_MAX_HEADER_LINE_SIZE,
216 max_header_count: DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT,
217 max_header_key_size: DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE,
218 max_header_value_size: DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE,
219 max_body_size: DEFAULT_LOW_SECURITY_MAX_BODY_SIZE,
220 max_ws_frame_size: DEFAULT_LOW_SECURITY_MAX_WS_FRAME_SIZE,
221 max_ws_frames_count: DEFAULT_LOW_SECURITY_MAX_WS_FRAMES_COUNT,
222 http_read_timeout_ms: DEFAULT_LOW_SECURITY_HTTP_READ_TIMEOUT_MS,
223 ws_read_timeout_ms: DEFAULT_LOW_SECURITY_WS_READ_TIMEOUT_MS,
224 }
225 }
226
227 /// Creates a config optimized for high-security environments.
228 ///
229 /// This configuration uses more restrictive limits to provide
230 /// maximum protection against various attacks.
231 ///
232 /// # Returns
233 ///
234 /// - `RequestConfigData ` - A new config with high-security settings.
235 #[inline(always)]
236 pub(super) fn high_security() -> Self {
237 Self {
238 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
239 max_request_line_size: DEFAULT_HIGH_SECURITY_MAX_REQUEST_LINE_SIZE,
240 max_path_size: DEFAULT_HIGH_SECURITY_MAX_PATH_SIZE,
241 max_query_size: DEFAULT_HIGH_SECURITY_MAX_QUERY_SIZE,
242 max_header_line_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_LINE_SIZE,
243 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
244 max_header_key_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_SIZE,
245 max_header_value_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_SIZE,
246 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
247 max_ws_frame_size: DEFAULT_HIGH_SECURITY_MAX_WS_FRAME_SIZE,
248 max_ws_frames_count: DEFAULT_HIGH_SECURITY_MAX_WS_FRAMES_COUNT,
249 http_read_timeout_ms: DEFAULT_HIGH_SECURITY_HTTP_READ_TIMEOUT_MS,
250 ws_read_timeout_ms: DEFAULT_HIGH_SECURITY_WS_READ_TIMEOUT_MS,
251 }
252 }
253}
254
255/// Implementation of `Default` trait for `RequestConfig`.
256impl Default for RequestConfig {
257 /// Creates a new `RequestConfig` with default secure settings.
258 ///
259 /// This constructor initializes the configuration with standard security limits
260 /// suitable for most HTTP request parsing scenarios.
261 ///
262 /// # Returns
263 ///
264 /// - `Self` - A new `RequestConfig` instance with default settings.
265 #[inline(always)]
266 fn default() -> Self {
267 Self(arc_rwlock(RequestConfigData::default()))
268 }
269}
270
271/// Implementation of `PartialEq` trait for `RequestConfig`.
272impl PartialEq for RequestConfig {
273 /// Compares two `RequestConfig` instances for equality.
274 ///
275 /// # Arguments
276 ///
277 /// - `other` - The second `RequestConfig` instance to compare.
278 ///
279 /// # Returns
280 ///
281 /// - `bool` - `true` if the instances are equal, `false` otherwise.
282 fn eq(&self, other: &Self) -> bool {
283 if Arc::ptr_eq(self.get_0(), other.get_0()) {
284 return true;
285 }
286 if let (Ok(s), Ok(o)) = (self.get_0().try_read(), other.get_0().try_read()) {
287 *s == *o
288 } else {
289 false
290 }
291 }
292}
293
294/// Implementation of `Eq` trait for `RequestConfig`.
295impl Eq for RequestConfig {}
296
297/// Implementation of `From` trait for `RequestConfig`.
298impl From<RequestConfigData> for RequestConfig {
299 /// Converts a `RequestConfigData` into a `RequestConfig`.
300 ///
301 /// # Arguments
302 ///
303 /// - `RequestConfigData` - The wrapped context data.
304 ///
305 /// # Returns
306 ///
307 /// - `RequestConfig` - The newly created context instance.
308 #[inline(always)]
309 fn from(ctx: RequestConfigData) -> Self {
310 Self(arc_rwlock(ctx))
311 }
312}
313
314impl RequestConfig {
315 /// Creates a new `RequestConfig` with default secure settings.
316 ///
317 /// This constructor initializes the configuration with standard security limits
318 /// suitable for most HTTP request parsing scenarios.
319 ///
320 /// # Returns
321 ///
322 /// - `Self` - A new `RequestConfig` instance with default settings.
323 pub async fn new() -> Self {
324 Self(arc_rwlock(RequestConfigData::default()))
325 }
326
327 /// Creates a new `RequestConfig` from a JSON string.
328 ///
329 /// # Arguments
330 ///
331 /// - `AsRef<str>` - The configuration.
332 ///
333 /// # Returns
334 ///
335 /// - `Result<RequestConfig, serde_json::Error>` - The parsed `RequestConfig` or an error.
336 pub fn from_json<C>(json: C) -> Result<RequestConfig, serde_json::Error>
337 where
338 C: AsRef<str>,
339 {
340 serde_json::from_str(json.as_ref()).map(|data: RequestConfigData| Self::from(data))
341 }
342
343 /// Creates a new `RequestConfig` with low-security settings.
344 ///
345 /// This constructor initializes the configuration with less restrictive limits
346 /// to provide maximum protection against various attacks in high-risk environments.
347 ///
348 /// # Returns
349 ///
350 /// - `Self` - A new `RequestConfig` instance with low-security settings.
351 pub async fn low_security() -> Self {
352 Self(arc_rwlock(RequestConfigData::low_security()))
353 }
354
355 /// Creates a new `RequestConfig` with high-security settings.
356 ///
357 /// This constructor initializes the configuration with more restrictive limits
358 /// to provide maximum protection against various attacks in high-risk environments.
359 ///
360 /// # Returns
361 ///
362 /// - `Self` - A new `RequestConfig` instance with high-security settings.
363 pub async fn high_security() -> Self {
364 Self(arc_rwlock(RequestConfigData::high_security()))
365 }
366
367 /// Acquires a read lock on the inner configuration.
368 ///
369 /// This method returns a `RwLockReadGuard` that allows reading the
370 /// `RequestConfigData ` values. Multiple threads can read concurrently.
371 ///
372 /// # Returns
373 ///
374 /// - `RwLockReadGuard<'_, RequestConfigData >` - A read guard providing access to the inner configuration.
375 async fn read(&'_ self) -> RwLockReadGuard<'_, RequestConfigData> {
376 self.get_0().read().await
377 }
378
379 /// Acquires a write lock on the inner configuration.
380 ///
381 /// This method returns a `RwLockWriteGuard` that allows mutating the
382 /// `RequestConfigData ` values. Write access is exclusive.
383 ///
384 /// # Returns
385 ///
386 /// - `RwLockWriteGuard<'_, RequestConfigData >` - A write guard providing exclusive access to the inner configuration.
387 async fn write(&'_ self) -> RwLockWriteGuard<'_, RequestConfigData> {
388 self.get_0().write().await
389 }
390
391 /// Sets the configuration data.
392 ///
393 /// # Arguments
394 ///
395 /// - `RequestConfigData` - The configuration data.
396 ///
397 /// # Returns
398 ///
399 /// - `&Self` - The RequestConfig instance for chaining.
400 pub async fn data(&self, data: RequestConfigData) -> &Self {
401 *self.write().await = data;
402 self
403 }
404
405 /// Gets the configuration data.
406 ///
407 /// # Returns
408 ///
409 /// - `RequestConfigData ` - The inner configuration.
410 pub async fn get_data(&self) -> RequestConfigData {
411 *self.read().await
412 }
413
414 /// Sets the buffer size for reading operations.
415 ///
416 /// # Arguments
417 ///
418 /// - `usize` - The buffer size in bytes.
419 ///
420 /// # Returns
421 ///
422 /// - `&Self` - The RequestConfig instance for chaining.
423 pub async fn buffer_size(&self, buffer_size: usize) -> &Self {
424 self.write().await.set_buffer_size(buffer_size);
425 self
426 }
427
428 /// Sets the maximum length for HTTP request line in bytes.
429 ///
430 /// # Arguments
431 ///
432 /// - `usize` - The maximum request line size.
433 ///
434 /// # Returns
435 ///
436 /// - `&Self` - The RequestConfig instance for chaining.
437 pub async fn max_request_line_size(&self, size: usize) -> &Self {
438 self.write().await.set_max_request_line_size(size);
439 self
440 }
441
442 /// Sets the maximum length for URL path in bytes.
443 ///
444 /// # Arguments
445 ///
446 /// - `usize` - The maximum path length.
447 ///
448 /// # Returns
449 ///
450 /// - `&Self` - The RequestConfig instance for chaining.
451 pub async fn max_path_size(&self, size: usize) -> &Self {
452 self.write().await.set_max_path_size(size);
453 self
454 }
455
456 /// Sets the maximum length for query string in bytes.
457 ///
458 /// # Arguments
459 ///
460 /// - `usize` - The maximum query string length.
461 ///
462 /// # Returns
463 ///
464 /// - `&Self` - The RequestConfig instance for chaining.
465 pub async fn max_query_size(&self, size: usize) -> &Self {
466 self.write().await.set_max_query_size(size);
467 self
468 }
469
470 /// Sets the maximum length for a single header line in bytes.
471 ///
472 /// # Arguments
473 ///
474 /// - `usize` - The maximum header line size.
475 ///
476 /// # Returns
477 ///
478 /// - `&Self` - The RequestConfig instance for chaining.
479 pub async fn max_header_line_size(&self, size: usize) -> &Self {
480 self.write().await.set_max_header_line_size(size);
481 self
482 }
483
484 /// Sets the maximum number of headers allowed in a request.
485 ///
486 /// # Arguments
487 ///
488 /// - `usize` - The maximum header count.
489 ///
490 /// # Returns
491 ///
492 /// - `&Self` - The RequestConfig instance for chaining.
493 pub async fn max_header_count(&self, count: usize) -> &Self {
494 self.write().await.set_max_header_count(count);
495 self
496 }
497
498 /// Sets the maximum length for a header key in bytes.
499 ///
500 /// # Arguments
501 ///
502 /// - `usize` - The maximum header key length.
503 ///
504 /// # Returns
505 ///
506 /// - `&Self` - The RequestConfig instance for chaining.
507 pub async fn max_header_key_size(&self, size: usize) -> &Self {
508 self.write().await.set_max_header_key_size(size);
509 self
510 }
511
512 /// Sets the maximum length for a header value in bytes.
513 ///
514 /// # Arguments
515 ///
516 /// - `usize` - The maximum header value length.
517 ///
518 /// # Returns
519 ///
520 /// - `&Self` - The RequestConfig instance for chaining.
521 pub async fn max_header_value_size(&self, size: usize) -> &Self {
522 self.write().await.set_max_header_value_size(size);
523 self
524 }
525
526 /// Sets the maximum size for request body in bytes.
527 ///
528 /// # Arguments
529 ///
530 /// - `usize` - The maximum body size.
531 ///
532 /// # Returns
533 ///
534 /// - `&Self` - The RequestConfig instance for chaining.
535 pub async fn max_body_size(&self, size: usize) -> &Self {
536 self.write().await.set_max_body_size(size);
537 self
538 }
539
540 /// Sets the maximum size for WebSocket frame in bytes.
541 ///
542 /// # Arguments
543 ///
544 /// - `usize` - The maximum WebSocket frame size.
545 ///
546 /// # Returns
547 ///
548 /// - `&Self` - The RequestConfig instance for chaining.
549 pub async fn max_ws_frame_size(&self, size: usize) -> &Self {
550 self.write().await.set_max_ws_frame_size(size);
551 self
552 }
553
554 /// Sets the maximum number of WebSocket frames to process in a single request.
555 ///
556 /// # Arguments
557 ///
558 /// - `usize` - The maximum WebSocket frames count.
559 ///
560 /// # Returns
561 ///
562 /// - `&Self` - The RequestConfig instance for chaining.
563 pub async fn max_ws_frames_count(&self, size: usize) -> &Self {
564 self.write().await.set_max_ws_frames_count(size);
565 self
566 }
567
568 /// Sets the timeout for reading HTTP request in milliseconds.
569 ///
570 /// # Arguments
571 ///
572 /// - `u64` - The HTTP read timeout in milliseconds.
573 ///
574 /// # Returns
575 ///
576 /// - `&Self` - The RequestConfig instance for chaining.
577 pub async fn http_read_timeout_ms(&self, http_read_timeout_ms: u64) -> &Self {
578 self.write()
579 .await
580 .set_http_read_timeout_ms(http_read_timeout_ms);
581 self
582 }
583
584 /// Sets the timeout for reading WebSocket frames in milliseconds.
585 ///
586 /// # Arguments
587 ///
588 /// - `u64` - The WebSocket read timeout in milliseconds.
589 ///
590 /// # Returns
591 ///
592 /// - `&Self` - The RequestConfig instance for chaining.
593 pub async fn ws_read_timeout_ms(&self, ws_read_timeout_ms: u64) -> &Self {
594 self.write()
595 .await
596 .set_ws_read_timeout_ms(ws_read_timeout_ms);
597 self
598 }
599}
600
601/// Provides a default value for `Request`.
602///
603/// Returns a new `Request` instance with all fields initialized to their default values.
604impl Default for Request {
605 #[inline(always)]
606 fn default() -> Self {
607 Self {
608 method: Method::default(),
609 host: String::new(),
610 version: HttpVersion::default(),
611 path: String::new(),
612 querys: hash_map_xx_hash3_64(),
613 headers: hash_map_xx_hash3_64(),
614 body: Vec::new(),
615 }
616 }
617}
618
619impl Http {
620 /// Reads the HTTP request line from the buffered reader.
621 ///
622 /// # Arguments
623 ///
624 /// - `&mut BufReader<&mut TcpStream>`: The buffered reader to read from.
625 /// - `usize`: The buffer size for initial string capacity.
626 /// - `usize`: The maximum allowed request line size.
627 ///
628 /// # Returns
629 ///
630 /// - `Result<String, RequestError>`: The request line string or an error.
631 #[inline(always)]
632 async fn check_first_line(
633 reader: &mut BufReader<&mut TcpStream>,
634 buffer_size: usize,
635 max_size: usize,
636 ) -> Result<String, RequestError> {
637 let mut line: String = String::with_capacity(buffer_size);
638 let size: usize = AsyncBufReadExt::read_line(reader, &mut line).await?;
639 if size > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_REQUEST_LINE_SIZE {
640 return Err(RequestError::RequestTooLong(HttpStatus::BadRequest));
641 }
642 Ok(line)
643 }
644
645 /// Parses the first line of HTTP request into method, path, and version components.
646 ///
647 /// # Arguments
648 ///
649 /// - `&str`: The first line string of HTTP request to parse.
650 ///
651 /// # Returns
652 ///
653 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>`: A tuple containing:
654 /// - The parsed HTTP method
655 /// - The full path string
656 /// - The parsed HTTP version
657 /// - Or an error if parsing fails
658 #[inline(always)]
659 fn parse_first_line(line: &str) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
660 let mut parts = line.split_whitespace();
661 let method_str: &str = parts
662 .next()
663 .ok_or(RequestError::HttpRequestPartsInsufficient(
664 HttpStatus::BadRequest,
665 ))?;
666 let full_path: &str = parts
667 .next()
668 .ok_or(RequestError::HttpRequestPartsInsufficient(
669 HttpStatus::BadRequest,
670 ))?;
671 let version_str: &str = parts
672 .next()
673 .ok_or(RequestError::HttpRequestPartsInsufficient(
674 HttpStatus::BadRequest,
675 ))?;
676 let method: RequestMethod = method_str
677 .parse::<RequestMethod>()
678 .unwrap_or_else(|_| Method::Unknown(method_str.to_string()));
679 let version: RequestVersion = version_str
680 .parse::<RequestVersion>()
681 .unwrap_or_else(|_| RequestVersion::Unknown(version_str.to_string()));
682 Ok((method, full_path, version))
683 }
684
685 /// Validates the path length against the maximum allowed size.
686 ///
687 /// # Arguments
688 ///
689 /// - `&str`: The path string to check.
690 /// - `usize`: The maximum allowed path size.
691 ///
692 /// # Returns
693 ///
694 /// - `Result<(), RequestError>`: Ok if valid, or an error if the path is too long.
695 #[inline(always)]
696 fn check_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
697 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
698 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
699 }
700 Ok(())
701 }
702
703 /// Parses the query string from the full path.
704 ///
705 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
706 /// ensuring proper parsing when both are present.
707 ///
708 /// # Arguments
709 ///
710 /// - `&str`: The full path string containing the query.
711 /// - `Option<usize>`: The index of the query separator (`?`), if present.
712 /// - `Option<usize>`: The index of the hash separator (`#`), if present.
713 ///
714 /// # Returns
715 ///
716 /// - `&str`: The parsed query string slice, or empty string if no query.
717 #[inline(always)]
718 fn get_query_slice<'a>(
719 path: &'a str,
720 query_index: Option<usize>,
721 hash_index: Option<usize>,
722 ) -> &'a str {
723 query_index.map_or(EMPTY_STR, |i: usize| {
724 let temp: &'a str = &path[i + 1..];
725 match hash_index {
726 None => temp,
727 Some(hash_idx) if hash_idx <= i => temp,
728 Some(hash_idx) => &temp[..hash_idx - i - 1],
729 }
730 })
731 }
732
733 /// Validates the query string length against the maximum allowed size.
734 ///
735 /// # Arguments
736 ///
737 /// - `&str`: The query string to check.
738 /// - `usize`: The maximum allowed query size.
739 ///
740 /// # Returns
741 ///
742 /// - `Result<(), RequestError>`: Ok if valid, or an error if the query is too long.
743 #[inline(always)]
744 fn check_query_size(query: &str, max_size: usize) -> Result<(), RequestError> {
745 if query.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_QUERY_SIZE {
746 return Err(RequestError::QueryTooLong(HttpStatus::URITooLong));
747 }
748 Ok(())
749 }
750
751 /// Parses the request path without query string or hash fragment.
752 ///
753 /// # Arguments
754 ///
755 /// - `&str`: The full path string.
756 /// - `Option<usize>`: The index of the query separator (`?`), if present.
757 /// - `Option<usize>`: The index of the hash separator (`#`), if present.
758 ///
759 /// # Returns
760 ///
761 /// - `RequestPath`: The request path without query or hash.
762 #[inline(always)]
763 fn parse_path(
764 path: &str,
765 query_index: Option<usize>,
766 hash_index: Option<usize>,
767 ) -> RequestPath {
768 match query_index.or(hash_index) {
769 Some(i) => path[..i].to_owned(),
770 None => path.to_owned(),
771 }
772 }
773
774 /// Parses a query string as_ref key-value pairs.
775 ///
776 /// Expects format "key1=value1&key2=value2". Empty values are allowed.
777 ///
778 /// # Arguments
779 ///
780 /// - `&str` - The query string to parse.
781 ///
782 /// # Returns
783 ///
784 /// - `RequestQuerys` - The parsed query parameters.
785 #[inline(always)]
786 fn parse_querys(query: &str) -> RequestQuerys {
787 let estimated_capacity: usize = query.matches(AND).count() + 1;
788 let mut query_map: RequestQuerys = HashMapXxHash3_64::with_capacity_and_hasher(
789 estimated_capacity,
790 BuildHasherDefault::default(),
791 );
792 for pair in query.split(AND) {
793 if let Some((key, value)) = pair.split_once(EQUAL) {
794 if !key.is_empty() {
795 query_map.insert(key.to_string(), value.to_string());
796 }
797 } else if !pair.is_empty() {
798 query_map.insert(pair.to_string(), String::new());
799 }
800 }
801 query_map
802 }
803
804 /// Checks if a header line exceeds the maximum allowed length.
805 ///
806 /// # Arguments
807 ///
808 /// - `usize`: The number of bytes read for the header line.
809 /// - `usize`: The maximum allowed length for a header line.
810 ///
811 /// # Returns
812 ///
813 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
814 #[inline(always)]
815 fn check_header_line_size(size: usize, max_size: usize) -> Result<(), RequestError> {
816 if size > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_LINE_SIZE {
817 return Err(RequestError::HeaderLineTooLong(
818 HttpStatus::RequestHeaderFieldsTooLarge,
819 ));
820 }
821 Ok(())
822 }
823
824 /// Checks if the header count exceeds the maximum allowed.
825 ///
826 /// # Arguments
827 ///
828 /// - `usize`: The current number of headers parsed.
829 /// - `usize`: The maximum allowed number of headers.
830 ///
831 /// # Returns
832 ///
833 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
834 #[inline(always)]
835 fn check_header_count(count: usize, max_count: usize) -> Result<(), RequestError> {
836 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
837 return Err(RequestError::TooManyHeaders(
838 HttpStatus::RequestHeaderFieldsTooLarge,
839 ));
840 }
841 Ok(())
842 }
843
844 /// Checks if a header key exceeds the maximum allowed length.
845 ///
846 /// # Arguments
847 ///
848 /// - `&str`: The header key to check.
849 /// - `usize`: The maximum allowed length for a header key.
850 ///
851 /// # Returns
852 ///
853 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
854 #[inline(always)]
855 fn check_header_key_size(key: &str, max_size: usize) -> Result<(), RequestError> {
856 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
857 return Err(RequestError::HeaderKeyTooLong(
858 HttpStatus::RequestHeaderFieldsTooLarge,
859 ));
860 }
861 Ok(())
862 }
863
864 /// Checks if a header value exceeds the maximum allowed length.
865 ///
866 /// # Arguments
867 ///
868 /// - `&str`: The header value to check.
869 /// - `usize`: The maximum allowed length for a header value.
870 ///
871 /// # Returns
872 ///
873 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
874 #[inline(always)]
875 fn check_header_value_size(value: &str, max_size: usize) -> Result<(), RequestError> {
876 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
877 return Err(RequestError::HeaderValueTooLong(
878 HttpStatus::RequestHeaderFieldsTooLarge,
879 ));
880 }
881 Ok(())
882 }
883
884 /// Parses the Content-Length header value and checks it against max body size.
885 ///
886 /// # Arguments
887 ///
888 /// - `&str`: The Content-Length header value string.
889 /// - `usize`: The maximum allowed body size.
890 ///
891 /// # Returns
892 ///
893 /// - `Result<usize, RequestError>`: The parsed content length or an error.
894 #[inline(always)]
895 fn check_body_size(value: &str, max_size: usize) -> Result<usize, RequestError> {
896 let length: usize = value.parse::<usize>()?;
897 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
898 return Err(RequestError::ContentLengthTooLarge(
899 HttpStatus::PayloadTooLarge,
900 ));
901 }
902 Ok(length)
903 }
904
905 /// Parses HTTP headers from a buffered reader.
906 ///
907 /// This method reads header lines from the provided buffered reader until an empty line
908 /// is encountered, which indicates the end of headers. It checks header count, length,
909 /// and content according to the provided configuration.
910 ///
911 /// # Arguments
912 ///
913 /// - `&mut AsyncBufReadExt + Unpin`: A mutable reference to a buffered reader implementing `AsyncBufReadExt`.
914 /// - `&RequestConfigData`: Configuration for security limits and buffer settings.
915 ///
916 /// # Returns
917 ///
918 /// - `Result<(RequestHeaders, RequestHost, usize), RequestError>`: A tuple containing:
919 /// - The parsed headers as a hash map
920 /// - The host value parsed from the Host header
921 /// - The content length parsed from the Content-Length header
922 /// - Or an error if parsing fails
923 async fn parse_headers<R>(
924 reader: &mut R,
925 config: &RequestConfigData,
926 ) -> Result<(RequestHeaders, RequestHost, usize), RequestError>
927 where
928 R: AsyncBufReadExt + Unpin,
929 {
930 let buffer_size: usize = config.get_buffer_size();
931 let max_header_line_size: usize = config.get_max_header_line_size();
932 let max_header_count: usize = config.get_max_header_count();
933 let max_header_key_size: usize = config.get_max_header_key_size();
934 let max_header_value_size: usize = config.get_max_header_value_size();
935 let max_body_size: usize = config.get_max_body_size();
936 let mut headers: RequestHeaders = HashMapXxHash3_64::with_capacity_and_hasher(
937 max_header_count.min(64),
938 BuildHasherDefault::default(),
939 );
940 let mut host: RequestHost = String::new();
941 let mut content_size: usize = 0;
942 let mut header_count: usize = 0;
943 let mut header_line_buffer: String = String::with_capacity(buffer_size);
944 loop {
945 header_line_buffer.clear();
946 let bytes_read: usize =
947 AsyncBufReadExt::read_line(reader, &mut header_line_buffer).await?;
948 Self::check_header_line_size(bytes_read, max_header_line_size)?;
949 let header_line: &str = header_line_buffer.trim();
950 if header_line.is_empty() {
951 break;
952 }
953 header_count += 1;
954 Self::check_header_count(header_count, max_header_count)?;
955 let (key_part, value_part): (&str, &str) = match header_line.split_once(COLON) {
956 Some(parts) => parts,
957 None => continue,
958 };
959 let key_trimmed: &str = key_part.trim();
960 if key_trimmed.is_empty() {
961 continue;
962 }
963 let key: String = key_trimmed.to_ascii_lowercase();
964 Self::check_header_key_size(&key, max_header_key_size)?;
965 let value: String = value_part.trim().to_string();
966 Self::check_header_value_size(&value, max_header_value_size)?;
967 match key.as_str() {
968 HOST => host = value.clone(),
969 CONTENT_LENGTH => {
970 content_size = Self::check_body_size(&value, max_body_size)?;
971 }
972 _ => {}
973 }
974 headers.entry(key).or_default().push_back(value);
975 }
976 Ok((headers, host, content_size))
977 }
978
979 /// Reads the request body from the buffered reader.
980 ///
981 /// # Arguments
982 ///
983 /// - `&mut BufReader<&mut TcpStream>`: The buffered reader to read from.
984 /// - `usize`: The expected content size.
985 ///
986 /// # Returns
987 ///
988 /// - `Result<RequestBody, RequestError>`: The body bytes or an error.
989 #[inline(always)]
990 async fn parse_body(
991 reader: &mut BufReader<&mut TcpStream>,
992 content_size: usize,
993 ) -> Result<RequestBody, RequestError> {
994 let mut body: RequestBody = Vec::with_capacity(content_size);
995 if content_size > 0 {
996 body.resize(content_size, 0);
997 AsyncReadExt::read_exact(reader, &mut body).await?;
998 }
999 Ok(body)
1000 }
1001
1002 /// Parses the HTTP request content from the stream.
1003 ///
1004 /// This is an internal helper function that performs the actual parsing.
1005 ///
1006 /// # Arguments
1007 ///
1008 /// - `&ArcRwLock<TcpStream>`: The TCP stream to read from.
1009 /// - `&RequestConfigData`: Configuration for security limits and buffer settings.
1010 ///
1011 /// # Returns
1012 ///
1013 /// - `Result<Request, RequestError>`: The parsed request or an error.
1014 async fn parse_from_stream(
1015 stream: &ArcRwLockStream,
1016 config: &RequestConfigData,
1017 ) -> Result<Request, RequestError> {
1018 let buffer_size: usize = config.get_buffer_size();
1019 let max_request_line_size: usize = config.get_max_request_line_size();
1020 let max_path_size: usize = config.get_max_path_size();
1021 let max_query_size: usize = config.get_max_query_size();
1022 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
1023 let reader: &mut BufReader<&mut TcpStream> =
1024 &mut BufReader::with_capacity(buffer_size, &mut buf_stream);
1025 let line: String =
1026 Self::check_first_line(reader, buffer_size, max_request_line_size).await?;
1027 let (method, path, version): (RequestMethod, &str, RequestVersion) =
1028 Self::parse_first_line(&line)?;
1029 Self::check_path_size(path, max_path_size)?;
1030 let hash_index: Option<usize> = path.find(HASH);
1031 let query_index: Option<usize> = path.find(QUERY);
1032 let query_slice: &str = Self::get_query_slice(path, query_index, hash_index);
1033 Self::check_query_size(query_slice, max_query_size)?;
1034 let querys: RequestQuerys = Self::parse_querys(query_slice);
1035 let path: RequestPath = Self::parse_path(path, query_index, hash_index);
1036 let (headers, host, content_size): (RequestHeaders, RequestHost, usize) =
1037 Self::parse_headers(reader, config).await?;
1038 let body: RequestBody = Self::parse_body(reader, content_size).await?;
1039 Ok(Request {
1040 method,
1041 host,
1042 version,
1043 path,
1044 querys,
1045 headers,
1046 body,
1047 })
1048 }
1049}
1050
1051impl Ws {
1052 /// Checks if the WebSocket frame count exceeds the maximum allowed.
1053 ///
1054 /// # Arguments
1055 ///
1056 /// - `usize`: The current number of frames.
1057 /// - `usize`: The maximum allowed number of frames.
1058 ///
1059 /// # Returns
1060 ///
1061 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
1062 #[inline(always)]
1063 fn check_frame_count(count: usize, max_count: usize) -> Result<(), RequestError> {
1064 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_WS_FRAMES_COUNT {
1065 return Err(RequestError::TooManyHeaders(
1066 HttpStatus::RequestHeaderFieldsTooLarge,
1067 ));
1068 }
1069 Ok(())
1070 }
1071
1072 /// Reads data from the stream with optional timeout handling.
1073 ///
1074 /// # Arguments
1075 ///
1076 /// - `&ArcRwLockStream`: The TCP stream to read from.
1077 /// - `&mut [u8]`: The buffer to read data into.
1078 /// - `Option<Duration>`: The optional timeout duration. If Some, timeout is applied; if None, no timeout.
1079 /// - `&mut bool`: Mutable reference to track if we got a client response.
1080 ///
1081 /// # Returns
1082 ///
1083 /// - `Result<Option<usize>, RequestError>`: The number of bytes read, None for timeout/ping, or an error.
1084 async fn read(
1085 stream: &ArcRwLockStream,
1086 buffer: &mut [u8],
1087 duration_opt: Option<Duration>,
1088 is_client_response: &mut bool,
1089 ) -> Result<Option<usize>, RequestError> {
1090 if let Some(duration) = duration_opt {
1091 return match timeout(duration, stream.write().await.read(buffer)).await {
1092 Ok(result) => match result {
1093 Ok(len) => Ok(Some(len)),
1094 Err(error) => Err(error.into()),
1095 },
1096 Err(error) => {
1097 if !*is_client_response {
1098 return Err(error.into());
1099 }
1100 *is_client_response = false;
1101 stream.try_send_body(&PING_FRAME).await?;
1102 Ok(None)
1103 }
1104 };
1105 }
1106 match stream.write().await.read(buffer).await {
1107 Ok(len) => Ok(Some(len)),
1108 Err(error) => Err(error.into()),
1109 }
1110 }
1111
1112 /// Handles a decoded WebSocket Text or Binary frame and accumulates payload data.
1113 ///
1114 /// # Arguments
1115 ///
1116 /// - `&Request`: The request to update on completion.
1117 /// - `&WebSocketFrame`: The decoded WebSocket frame.
1118 /// - `&mut Vec<u8>`: The accumulated frame data.
1119 /// - `usize`: Maximum allowed frame size.
1120 ///
1121 /// # Returns
1122 ///
1123 /// - `Result<Option<Request>, RequestError>`: Some(request) if frame is complete, None to continue, or error.
1124 #[inline(always)]
1125 fn parse_frame(
1126 request: &Request,
1127 frame: &WebSocketFrame,
1128 full_frame: &mut Vec<u8>,
1129 max_size: usize,
1130 ) -> Result<Option<Request>, RequestError> {
1131 let payload_data: &[u8] = frame.get_payload_data();
1132 let payload_data_len: usize = payload_data.len();
1133 if payload_data_len > max_size {
1134 return Err(RequestError::WebSocketFrameTooLarge(
1135 HttpStatus::PayloadTooLarge,
1136 ));
1137 }
1138 let sum_len: usize = full_frame.len() + payload_data_len;
1139 if sum_len > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_WS_FRAME_SIZE {
1140 return Err(RequestError::WebSocketFrameTooLarge(
1141 HttpStatus::PayloadTooLarge,
1142 ));
1143 }
1144 full_frame.extend_from_slice(payload_data);
1145 if *frame.get_fin() {
1146 let mut result: Request = request.clone();
1147 result.body = full_frame.clone();
1148 return Ok(Some(result));
1149 }
1150 Ok(None)
1151 }
1152}
1153
1154impl Request {
1155 /// Parses an HTTP request from a TCP stream.
1156 ///
1157 /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
1158 /// If the timeout is DEFAULT_LOW_SECURITY_HTTP_READ_TIMEOUT_MS, no timeout is applied.
1159 ///
1160 /// # Arguments
1161 ///
1162 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
1163 /// - `&RequestConfigData` - Configuration for security limits and buffer settings.
1164 ///
1165 /// # Returns
1166 ///
1167 /// - `Result<Request, RequestError>` - The parsed request or an error.
1168 pub async fn http_from_stream(
1169 stream: &ArcRwLockStream,
1170 config: &RequestConfigData,
1171 ) -> Result<Request, RequestError> {
1172 let timeout_ms: u64 = config.get_http_read_timeout_ms();
1173 if timeout_ms == DEFAULT_LOW_SECURITY_HTTP_READ_TIMEOUT_MS {
1174 return Http::parse_from_stream(stream, config).await;
1175 }
1176 let duration: Duration = Duration::from_millis(timeout_ms);
1177 timeout(duration, Http::parse_from_stream(stream, config)).await?
1178 }
1179
1180 /// Parses a WebSocket request from a TCP stream.
1181 ///
1182 /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
1183 /// If the timeout is DEFAULT_LOW_SECURITY_WS_READ_TIMEOUT_MS, no timeout is applied.
1184 ///
1185 /// # Arguments
1186 ///
1187 /// - `&ArcRwLock<TcpStream>`: The TCP stream to read from.
1188 /// - `&RequestConfigData`: Configuration for security limits and buffer settings.
1189 ///
1190 /// # Returns
1191 ///
1192 /// - `Result<Request, RequestError>`: The parsed WebSocket request or an error.
1193 pub async fn ws_from_stream(
1194 &self,
1195 stream: &ArcRwLockStream,
1196 config: &RequestConfigData,
1197 ) -> Result<Request, RequestError> {
1198 let buffer_size: usize = config.get_buffer_size();
1199 let max_ws_frame_size: usize = config.get_max_ws_frame_size();
1200 let ws_read_timeout_ms: u64 = config.get_ws_read_timeout_ms();
1201 let max_ws_frames_count: usize = config.get_max_ws_frames_count();
1202 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
1203 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
1204 let mut full_frame: Vec<u8> = Vec::with_capacity(max_ws_frame_size);
1205 let mut frame_count: usize = 0;
1206 let mut is_client_response: bool = false;
1207 let duration_opt: Option<Duration> =
1208 if ws_read_timeout_ms == DEFAULT_LOW_SECURITY_WS_READ_TIMEOUT_MS {
1209 None
1210 } else {
1211 let adjusted_timeout_ms: u64 = (ws_read_timeout_ms >> 1) + (ws_read_timeout_ms & 1);
1212 Some(Duration::from_millis(adjusted_timeout_ms))
1213 };
1214 loop {
1215 let len: usize = match Ws::read(
1216 stream,
1217 &mut temp_buffer,
1218 duration_opt,
1219 &mut is_client_response,
1220 )
1221 .await
1222 {
1223 Ok(Some(len)) => len,
1224 Ok(None) => continue,
1225 Err(error) => return Err(error),
1226 };
1227 if len == 0 {
1228 return Err(RequestError::IncompleteWebSocketFrame(
1229 HttpStatus::BadRequest,
1230 ));
1231 }
1232 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
1233 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
1234 is_client_response = true;
1235 dynamic_buffer.drain(0..consumed);
1236 frame_count += 1;
1237 Ws::check_frame_count(frame_count, max_ws_frames_count)?;
1238 match frame.get_opcode() {
1239 WebSocketOpcode::Close => {
1240 return Err(RequestError::ClientClosedConnection(HttpStatus::BadRequest));
1241 }
1242 WebSocketOpcode::Ping | WebSocketOpcode::Pong => continue,
1243 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
1244 match Ws::parse_frame(self, &frame, &mut full_frame, max_ws_frame_size) {
1245 Ok(Some(result)) => return Ok(result),
1246 Ok(None) => continue,
1247 Err(error) => return Err(error),
1248 }
1249 }
1250 _ => {
1251 return Err(RequestError::WebSocketOpcodeUnsupported(
1252 HttpStatus::NotImplemented,
1253 ));
1254 }
1255 }
1256 }
1257 }
1258 }
1259
1260 /// Tries to get a query parameter value by key.
1261 ///
1262 /// The key type must implement AsRef<str> conversion.
1263 ///
1264 /// # Arguments
1265 ///
1266 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
1267 ///
1268 /// # Returns
1269 ///
1270 /// - `Option<RequestQuerysValue>` - The parameter value if exists.
1271 #[inline(always)]
1272 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
1273 where
1274 K: AsRef<str>,
1275 {
1276 self.querys.get(key.as_ref()).cloned()
1277 }
1278
1279 /// Gets a query parameter value by key.
1280 ///
1281 /// The key type must implement AsRef<str> conversion.
1282 ///
1283 /// # Arguments
1284 ///
1285 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
1286 ///
1287 /// # Returns
1288 ///
1289 /// - `RequestQuerysValue` - The parameter value if exists.
1290 ///
1291 /// # Panics
1292 ///
1293 /// This function will panic if the query parameter key is not found.
1294 #[inline(always)]
1295 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
1296 where
1297 K: AsRef<str>,
1298 {
1299 self.try_get_query(key).unwrap()
1300 }
1301
1302 /// Tries to retrieve the value of a request header by its key.
1303 ///
1304 /// # Arguments
1305 ///
1306 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1307 ///
1308 /// # Returns
1309 ///
1310 /// - `Option<RequestHeadersValue>` - The optional header values.
1311 #[inline(always)]
1312 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
1313 where
1314 K: AsRef<str>,
1315 {
1316 self.headers.get(key.as_ref()).cloned()
1317 }
1318
1319 /// Retrieves the value of a request header by its key.
1320 ///
1321 /// # Arguments
1322 ///
1323 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1324 ///
1325 /// # Returns
1326 ///
1327 /// - `RequestHeadersValue` - The optional header values.
1328 ///
1329 /// # Panics
1330 ///
1331 /// This function will panic if the header key is not found.
1332 #[inline(always)]
1333 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
1334 where
1335 K: AsRef<str>,
1336 {
1337 self.try_get_header(key).unwrap()
1338 }
1339
1340 /// Tries to retrieve the first value of a request header by its key.
1341 ///
1342 /// # Arguments
1343 ///
1344 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1345 ///
1346 /// # Returns
1347 ///
1348 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
1349 #[inline(always)]
1350 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
1351 where
1352 K: AsRef<str>,
1353 {
1354 self.headers
1355 .get(key.as_ref())
1356 .and_then(|values| values.front().cloned())
1357 }
1358
1359 /// Retrieves the first value of a request header by its key.
1360 ///
1361 /// # Arguments
1362 ///
1363 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1364 ///
1365 /// # Returns
1366 ///
1367 /// - `RequestHeadersValueItem` - The first header value if exists.
1368 ///
1369 /// # Panics
1370 ///
1371 /// This function will panic if the header key is not found.
1372 #[inline(always)]
1373 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
1374 where
1375 K: AsRef<str>,
1376 {
1377 self.try_get_header_front(key).unwrap()
1378 }
1379
1380 /// Tries to retrieve the last value of a request header by its key.
1381 ///
1382 /// # Arguments
1383 ///
1384 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1385 ///
1386 /// # Returns
1387 ///
1388 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
1389 #[inline(always)]
1390 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
1391 where
1392 K: AsRef<str>,
1393 {
1394 self.headers
1395 .get(key.as_ref())
1396 .and_then(|values| values.back().cloned())
1397 }
1398
1399 /// Retrieves the last value of a request header by its key.
1400 ///
1401 /// # Arguments
1402 ///
1403 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1404 ///
1405 /// # Returns
1406 ///
1407 /// - `RequestHeadersValueItem` - The last header value if exists.
1408 ///
1409 /// # Panics
1410 ///
1411 /// This function will panic if the header key is not found.
1412 #[inline(always)]
1413 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
1414 where
1415 K: AsRef<str>,
1416 {
1417 self.try_get_header_back(key).unwrap()
1418 }
1419
1420 /// Tries to retrieve the number of values for a specific header.
1421 ///
1422 /// # Arguments
1423 ///
1424 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1425 ///
1426 /// # Returns
1427 ///
1428 /// - `Option<usize>` - The count of values for the header if exists.
1429 #[inline(always)]
1430 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
1431 where
1432 K: AsRef<str>,
1433 {
1434 self.headers.get(key.as_ref()).map(|values| values.len())
1435 }
1436
1437 /// Retrieves the number of values for a specific header.
1438 ///
1439 /// # Arguments
1440 ///
1441 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
1442 ///
1443 /// # Returns
1444 ///
1445 /// - `usize` - The count of values for the header.
1446 ///
1447 /// # Panics
1448 ///
1449 /// This function will panic if the header key is not found.
1450 #[inline(always)]
1451 pub fn get_header_size<K>(&self, key: K) -> usize
1452 where
1453 K: AsRef<str>,
1454 {
1455 self.try_get_header_size(key).unwrap()
1456 }
1457
1458 /// Retrieves the total number of header values across all headers.
1459 ///
1460 /// # Returns
1461 ///
1462 /// - `usize` - The total count of all header values.
1463 #[inline(always)]
1464 pub fn get_headers_values_size(&self) -> usize {
1465 self.headers.values().map(|values| values.len()).sum()
1466 }
1467
1468 /// Retrieves the number of unique headers.
1469 ///
1470 /// # Returns
1471 ///
1472 /// - `usize` - The count of unique header keys.
1473 #[inline(always)]
1474 pub fn get_headers_size(&self) -> usize {
1475 self.headers.len()
1476 }
1477
1478 /// Checks if a specific header exists.
1479 ///
1480 /// # Arguments
1481 ///
1482 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
1483 ///
1484 /// # Returns
1485 ///
1486 /// - `bool` - Whether the header exists.
1487 #[inline(always)]
1488 pub fn has_header<K>(&self, key: K) -> bool
1489 where
1490 K: AsRef<str>,
1491 {
1492 self.headers.contains_key(key.as_ref())
1493 }
1494
1495 /// Checks if a header contains a specific value.
1496 ///
1497 /// # Arguments
1498 ///
1499 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
1500 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
1501 ///
1502 /// # Returns
1503 ///
1504 /// - `bool` - Whether the header contains the value.
1505 #[inline(always)]
1506 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
1507 where
1508 K: AsRef<str>,
1509 V: AsRef<str>,
1510 {
1511 if let Some(values) = self.headers.get(key.as_ref()) {
1512 values.iter().any(|v| v == value.as_ref())
1513 } else {
1514 false
1515 }
1516 }
1517
1518 /// Retrieves the upgrade type from the request headers.
1519 ///
1520 /// This method looks for the `UPGRADE` header and attempts to parse its value
1521 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
1522 /// it returns the default `UpgradeType`.
1523 ///
1524 /// # Returns
1525 ///
1526 /// - `UpgradeType` - The parsed upgrade type.
1527 #[inline(always)]
1528 pub fn get_upgrade_type(&self) -> UpgradeType {
1529 let upgrade_type: UpgradeType = self
1530 .try_get_header_back(UPGRADE)
1531 .and_then(|data| data.parse::<UpgradeType>().ok())
1532 .unwrap_or_default();
1533 upgrade_type
1534 }
1535
1536 /// Retrieves the body content of the request as a UTF-8 encoded string.
1537 ///
1538 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
1539 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
1540 ///
1541 /// # Returns
1542 ///
1543 /// - `String` - The body content as a string.
1544 #[inline(always)]
1545 pub fn get_body_string(&self) -> String {
1546 String::from_utf8_lossy(self.get_body()).into_owned()
1547 }
1548
1549 /// Deserializes the body content of the request as_ref a specified type `T`.
1550 ///
1551 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1552 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1553 ///
1554 /// # Arguments
1555 ///
1556 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1557 ///
1558 /// # Returns
1559 ///
1560 /// - `Result<T, serde_json::Error>` - The deserialization result.
1561 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1562 where
1563 T: DeserializeOwned,
1564 {
1565 serde_json::from_slice(self.get_body())
1566 }
1567
1568 /// Deserializes the body content of the request as_ref a specified type `T`.
1569 ///
1570 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1571 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1572 ///
1573 /// # Arguments
1574 ///
1575 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1576 ///
1577 /// # Returns
1578 ///
1579 /// - `T` - The deserialized body content.
1580 ///
1581 /// # Panics
1582 ///
1583 /// This function will panic if the deserialization fails.
1584 pub fn get_body_json<T>(&self) -> T
1585 where
1586 T: DeserializeOwned,
1587 {
1588 self.try_get_body_json().unwrap()
1589 }
1590
1591 /// Checks whether the request method is GET.
1592 ///
1593 /// # Returns
1594 ///
1595 /// - `bool` - Whether the method is GET.
1596 #[inline(always)]
1597 pub fn is_get_method(&self) -> bool {
1598 self.get_method().is_get()
1599 }
1600
1601 /// Checks whether the request method is POST.
1602 ///
1603 /// # Returns
1604 ///
1605 /// - `bool` - Whether the method is POST.
1606 #[inline(always)]
1607 pub fn is_post_method(&self) -> bool {
1608 self.get_method().is_post()
1609 }
1610
1611 /// Checks whether the request method is PUT.
1612 ///
1613 /// # Returns
1614 ///
1615 /// - `bool` - Whether the method is PUT.
1616 #[inline(always)]
1617 pub fn is_put_method(&self) -> bool {
1618 self.get_method().is_put()
1619 }
1620
1621 /// Checks whether the request method is DELETE.
1622 ///
1623 /// # Returns
1624 ///
1625 /// - `bool` - Whether the method is DELETE.
1626 #[inline(always)]
1627 pub fn is_delete_method(&self) -> bool {
1628 self.get_method().is_delete()
1629 }
1630
1631 /// Checks whether the request method is PATCH.
1632 ///
1633 /// # Returns
1634 ///
1635 /// - `bool` - Whether the method is PATCH.
1636 #[inline(always)]
1637 pub fn is_patch_method(&self) -> bool {
1638 self.get_method().is_patch()
1639 }
1640
1641 /// Checks whether the request method is HEAD.
1642 ///
1643 /// # Returns
1644 ///
1645 /// - `bool` - Whether the method is HEAD.
1646 #[inline(always)]
1647 pub fn is_head_method(&self) -> bool {
1648 self.get_method().is_head()
1649 }
1650
1651 /// Checks whether the request method is OPTIONS.
1652 ///
1653 /// # Returns
1654 ///
1655 /// - `bool` - Whether the method is OPTIONS.
1656 #[inline(always)]
1657 pub fn is_options_method(&self) -> bool {
1658 self.get_method().is_options()
1659 }
1660
1661 /// Checks whether the request method is CONNECT.
1662 ///
1663 /// # Returns
1664 ///
1665 /// - `bool` - Whether the method is CONNECT.
1666 #[inline(always)]
1667 pub fn is_connect_method(&self) -> bool {
1668 self.get_method().is_connect()
1669 }
1670
1671 /// Checks whether the request method is TRACE.
1672 ///
1673 /// # Returns
1674 ///
1675 /// - `bool` - Whether the method is TRACE.
1676 #[inline(always)]
1677 pub fn is_trace_method(&self) -> bool {
1678 self.get_method().is_trace()
1679 }
1680
1681 /// Checks whether the request method is UNKNOWN.
1682 ///
1683 /// # Returns
1684 ///
1685 /// - `bool` - Whether the method is UNKNOWN.
1686 #[inline(always)]
1687 pub fn is_unknown_method(&self) -> bool {
1688 self.get_method().is_unknown()
1689 }
1690
1691 /// Checks whether the HTTP version is HTTP/0.9.
1692 ///
1693 /// # Returns
1694 ///
1695 /// - `bool` - Whether the version is HTTP/0.9.
1696 #[inline(always)]
1697 pub fn is_http0_9_version(&self) -> bool {
1698 self.get_version().is_http0_9()
1699 }
1700
1701 /// Checks whether the HTTP version is HTTP/1.0.
1702 ///
1703 /// # Returns
1704 ///
1705 /// - `bool` - Whether the version is HTTP/1.0.
1706 #[inline(always)]
1707 pub fn is_http1_0_version(&self) -> bool {
1708 self.get_version().is_http1_0()
1709 }
1710
1711 /// Checks whether the HTTP version is HTTP/1.1.
1712 ///
1713 /// # Returns
1714 ///
1715 /// - `bool` - Whether the version is HTTP/1.1.
1716 #[inline(always)]
1717 pub fn is_http1_1_version(&self) -> bool {
1718 self.get_version().is_http1_1()
1719 }
1720
1721 /// Checks whether the HTTP version is HTTP/2.
1722 ///
1723 /// # Returns
1724 ///
1725 /// - `bool` - Whether the version is HTTP/2.
1726 #[inline(always)]
1727 pub fn is_http2_version(&self) -> bool {
1728 self.get_version().is_http2()
1729 }
1730
1731 /// Checks whether the HTTP version is HTTP/3.
1732 ///
1733 /// # Returns
1734 ///
1735 /// - `bool` - Whether the version is HTTP/3.
1736 #[inline(always)]
1737 pub fn is_http3_version(&self) -> bool {
1738 self.get_version().is_http3()
1739 }
1740
1741 /// Checks if the HTTP version is HTTP/1.1 or higher.
1742 ///
1743 /// # Returns
1744 ///
1745 /// - `bool` - Whether the version is HTTP/1.1 or higher.
1746 #[inline(always)]
1747 pub fn is_http1_1_or_higher_version(&self) -> bool {
1748 self.get_version().is_http1_1_or_higher()
1749 }
1750
1751 /// Checks whether the version belongs to the HTTP family.
1752 ///
1753 /// # Returns
1754 ///
1755 /// - `bool` - Whether the version is HTTP.
1756 #[inline(always)]
1757 pub fn is_http_version(&self) -> bool {
1758 self.get_version().is_http()
1759 }
1760
1761 /// Checks whether the HTTP version is unknown.
1762 ///
1763 /// # Returns
1764 ///
1765 /// - `bool` - Whether the version is unknown.
1766 #[inline(always)]
1767 pub fn is_unknown_version(&self) -> bool {
1768 self.get_version().is_unknown()
1769 }
1770
1771 /// Checks whether the WebSocket upgrade is enabled for this request.
1772 ///
1773 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1774 ///
1775 /// # Returns
1776 ///
1777 /// - `bool` - Whether WebSocket upgrade is enabled.
1778 #[inline(always)]
1779 pub fn is_ws_upgrade_type(&self) -> bool {
1780 self.get_upgrade_type().is_ws()
1781 }
1782
1783 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1784 ///
1785 /// # Returns
1786 ///
1787 /// - `bool` - Whether the upgrade type is h2c.
1788 #[inline(always)]
1789 pub fn is_h2c_upgrade_type(&self) -> bool {
1790 self.get_upgrade_type().is_h2c()
1791 }
1792
1793 /// Checks if the current upgrade type is TLS (any version).
1794 ///
1795 /// # Returns
1796 ///
1797 /// - `bool` - Whether the upgrade type is TLS.
1798 #[inline(always)]
1799 pub fn is_tls_upgrade_type(&self) -> bool {
1800 self.get_upgrade_type().is_tls()
1801 }
1802
1803 /// Checks whether the upgrade type is unknown.
1804 ///
1805 /// # Returns
1806 ///
1807 /// - `bool` - Whether the upgrade type is unknown.
1808 #[inline(always)]
1809 pub fn is_unknown_upgrade_type(&self) -> bool {
1810 self.get_upgrade_type().is_unknown()
1811 }
1812
1813 /// Determines if a keep-alive connection should be enabled for this request.
1814 ///
1815 /// This function checks the `Connection` header and the HTTP version to determine
1816 /// if keep-alive should be enabled. The logic is as follows:
1817 ///
1818 /// 1. If the `Connection` header exists:
1819 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1820 /// - Returns `false` if the header value is "close" (case-insensitive).
1821 /// 2. If no `Connection` header is present:
1822 /// - Returns `true` if the HTTP version is 1.1 or higher.
1823 /// - Returns `false` otherwise.
1824 ///
1825 /// # Returns
1826 ///
1827 /// - `bool` - Whether keep-alive should be enabled.
1828 #[inline(always)]
1829 pub fn is_enable_keep_alive(&self) -> bool {
1830 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1831 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1832 return true;
1833 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1834 return self.is_ws_upgrade_type();
1835 }
1836 }
1837 self.is_http1_1_or_higher_version() || self.is_ws_upgrade_type()
1838 }
1839
1840 /// Determines if keep-alive should be disabled for this request.
1841 ///
1842 /// # Returns
1843 ///
1844 /// - `bool` - Whether keep-alive should be disabled.
1845 #[inline(always)]
1846 pub fn is_disable_keep_alive(&self) -> bool {
1847 !self.is_enable_keep_alive()
1848 }
1849}