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