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