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