http_type/request/impl.rs
1use super::*;
2
3/// Implements the `std::error::Error` trait for `RequestError`.
4impl std::error::Error for RequestError {}
5
6/// Provides a default value for `RequestError`.
7impl Default for RequestError {
8 /// Provides a default value for `RequestError`.
9 ///
10 /// Returns a `RequestError::Unknown` with `HttpStatus::InternalServerError`.
11 #[inline(always)]
12 fn default() -> Self {
13 RequestError::Unknown(HttpStatus::InternalServerError)
14 }
15}
16
17/// Converts an I/O error to a `RequestError`.
18///
19/// Maps connection reset and aborted errors to `ClientDisconnected`,
20/// all other I/O errors are mapped to `ReadConnection`.
21impl From<std::io::Error> for RequestError {
22 /// Converts an I/O error to a `RequestError`.
23 ///
24 /// # Arguments
25 ///
26 /// - `std::io::Error` - The I/O error to convert.
27 ///
28 /// # Returns
29 ///
30 /// - `RequestError` - The corresponding request error.
31 #[inline(always)]
32 fn from(error: std::io::Error) -> Self {
33 let kind: ErrorKind = error.kind();
34 if kind == ErrorKind::ConnectionReset || kind == ErrorKind::ConnectionAborted {
35 return RequestError::ClientDisconnected(HttpStatus::BadRequest);
36 }
37 RequestError::ReadConnection(HttpStatus::BadRequest)
38 }
39}
40
41/// Converts a timeout elapsed error to a `RequestError`.
42///
43/// Maps timeout errors to `ReadTimeout` with `HttpStatus::RequestTimeout`.
44impl From<Elapsed> for RequestError {
45 /// Converts a timeout elapsed error to a `RequestError`.
46 ///
47 /// # Arguments
48 ///
49 /// - `Elapsed` - The elapsed error to convert.
50 ///
51 /// # Returns
52 ///
53 /// - `RequestError` - The corresponding request error as `ReadTimeout`.
54 #[inline(always)]
55 fn from(_: Elapsed) -> Self {
56 RequestError::ReadTimeout(HttpStatus::RequestTimeout)
57 }
58}
59
60/// Converts a parse int error to a `RequestError`.
61///
62/// Maps parse int errors to `InvalidContentLength` with `HttpStatus::BadRequest`.
63impl From<ParseIntError> for RequestError {
64 /// Converts a parse int error to a `RequestError`.
65 ///
66 /// # Arguments
67 ///
68 /// - `ParseIntError` - The parse error to convert.
69 ///
70 /// # Returns
71 ///
72 /// - `RequestError` - The corresponding request error as `InvalidContentLength`.
73 #[inline(always)]
74 fn from(_: ParseIntError) -> Self {
75 RequestError::InvalidContentLength(HttpStatus::BadRequest)
76 }
77}
78
79/// Converts a response error to a `RequestError`.
80///
81/// Maps response errors to `WriteTimeout` with `HttpStatus::InternalServerError`.
82impl From<ResponseError> for RequestError {
83 /// Converts a response error to a `RequestError`.
84 ///
85 /// # Arguments
86 ///
87 /// - `ResponseError` - The response error to convert.
88 ///
89 /// # Returns
90 ///
91 /// - `RequestError` - The corresponding request error as `WriteTimeout`.
92 #[inline(always)]
93 fn from(_: ResponseError) -> Self {
94 RequestError::WriteTimeout(HttpStatus::InternalServerError)
95 }
96}
97
98impl RequestError {
99 /// Gets the HTTP status associated with this error.
100 ///
101 /// Returns the HttpStatus enum variant that corresponds to this error.
102 ///
103 /// # Returns
104 ///
105 /// - `HttpStatus` - The HTTP status associated with this error.
106 pub fn get_http_status(&self) -> HttpStatus {
107 match self {
108 Self::HttpRead(status) => *status,
109 Self::GetTcpStream(status) => *status,
110 Self::GetTlsStream(status) => *status,
111 Self::ReadConnection(status) => *status,
112 Self::RequestAborted(status) => *status,
113 Self::TlsStreamConnect(status) => *status,
114 Self::NeedOpenRedirect(status) => *status,
115 Self::MaxRedirectTimes(status) => *status,
116 Self::MethodsNotSupport(status) => *status,
117 Self::RedirectInvalidUrl(status) => *status,
118 Self::ClientDisconnected(status) => *status,
119 Self::RedirectUrlDeadLoop(status) => *status,
120 Self::ClientClosedConnection(status) => *status,
121 Self::ServerClosedConnection(status) => *status,
122 Self::IncompleteWebSocketFrame(status) => *status,
123 Self::RequestTooLong(status) => *status,
124 Self::PathTooLong(status) => *status,
125 Self::QueryTooLong(status) => *status,
126 Self::HeaderLineTooLong(status) => *status,
127 Self::TooManyHeaders(status) => *status,
128 Self::HeaderKeyTooLong(status) => *status,
129 Self::HeaderValueTooLong(status) => *status,
130 Self::ContentLengthTooLarge(status) => *status,
131 Self::InvalidContentLength(status) => *status,
132 Self::InvalidUrlScheme(status) => *status,
133 Self::InvalidUrlHost(status) => *status,
134 Self::InvalidUrlPort(status) => *status,
135 Self::InvalidUrlPath(status) => *status,
136 Self::InvalidUrlQuery(status) => *status,
137 Self::InvalidUrlFragment(status) => *status,
138 Self::ReadTimeout(status) => *status,
139 Self::WriteTimeout(status) => *status,
140 Self::TcpConnectionFailed(status) => *status,
141 Self::TlsHandshakeFailed(status) => *status,
142 Self::TlsCertificateInvalid(status) => *status,
143 Self::WebSocketFrameTooLarge(status) => *status,
144 Self::WebSocketOpcodeUnsupported(status) => *status,
145 Self::WebSocketMaskMissing(status) => *status,
146 Self::WebSocketPayloadCorrupted(status) => *status,
147 Self::WebSocketInvalidUtf8(status) => *status,
148 Self::WebSocketInvalidCloseCode(status) => *status,
149 Self::WebSocketInvalidExtension(status) => *status,
150 Self::HttpRequestPartsInsufficient(status) => *status,
151 Self::TcpStreamConnect(status) => *status,
152 Self::TlsConnectorBuild(status) => *status,
153 Self::InvalidUrl(status) => *status,
154 Self::ConfigReadError(status) => *status,
155 Self::TcpStreamConnectString(status) => *status,
156 Self::TlsConnectorBuildString(status) => *status,
157 Self::Request(_) => HttpStatus::BadRequest,
158 Self::Unknown(status) => *status,
159 }
160 }
161
162 /// Gets the numeric HTTP status code associated with this error.
163 ///
164 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
165 ///
166 /// # Returns
167 ///
168 /// - `ResponseStatusCode` - The numeric HTTP status code.
169 pub fn get_http_status_code(&self) -> ResponseStatusCode {
170 self.get_http_status().code()
171 }
172}
173
174/// Implementation of `Default` trait for `RequestConfig`.
175impl Default for RequestConfig {
176 /// Creates a new `RequestConfig` with default secure settings.
177 ///
178 /// This constructor initializes the configuration with standard security limits
179 /// suitable for most HTTP request parsing scenarios.
180 ///
181 /// # Returns
182 ///
183 /// - `Self` - A new `RequestConfig` instance with default settings.
184 #[inline(always)]
185 fn default() -> Self {
186 Self {
187 buffer_size: DEFAULT_BUFFER_SIZE,
188 max_path_size: DEFAULT_MAX_PATH_SIZE,
189 max_header_count: DEFAULT_MAX_HEADER_COUNT,
190 max_header_key_size: DEFAULT_MAX_HEADER_KEY_SIZE,
191 max_header_value_size: DEFAULT_MAX_HEADER_VALUE_SIZE,
192 max_body_size: DEFAULT_MAX_BODY_SIZE,
193 read_timeout_ms: DEFAULT_READ_TIMEOUT_MS,
194 }
195 }
196}
197
198impl RequestConfig {
199 /// Creates a new `RequestConfig` from a JSON string.
200 ///
201 /// # Arguments
202 ///
203 /// - `AsRef<str>` - The configuration.
204 ///
205 /// # Returns
206 ///
207 /// - `Result<RequestConfig, serde_json::Error>` - The parsed `RequestConfig` or an error.
208 pub fn from_json<C>(json: C) -> Result<RequestConfig, serde_json::Error>
209 where
210 C: AsRef<str>,
211 {
212 serde_json::from_str(json.as_ref())
213 }
214
215 /// Creates a new `RequestConfig` with low-security settings.
216 ///
217 /// This constructor initializes the configuration with less restrictive limits
218 /// for environments where higher limits are needed.
219 ///
220 /// # Returns
221 ///
222 /// - `Self` - A new `RequestConfig` instance with low-security settings.
223 #[inline(always)]
224 pub fn low_security() -> Self {
225 Self {
226 buffer_size: DEFAULT_LOW_SECURITY_BUFFER_SIZE,
227 max_path_size: DEFAULT_LOW_SECURITY_MAX_PATH_SIZE,
228 max_header_count: DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT,
229 max_header_key_size: DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE,
230 max_header_value_size: DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE,
231 max_body_size: DEFAULT_LOW_SECURITY_MAX_BODY_SIZE,
232 read_timeout_ms: DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS,
233 }
234 }
235
236 /// Creates a new `RequestConfig` with high-security settings.
237 ///
238 /// This constructor initializes the configuration with more restrictive limits
239 /// to provide maximum protection against various attacks in high-risk environments.
240 ///
241 /// # Returns
242 ///
243 /// - `Self` - A new `RequestConfig` instance with high-security settings.
244 #[inline(always)]
245 pub fn high_security() -> Self {
246 Self {
247 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
248 max_path_size: DEFAULT_HIGH_SECURITY_MAX_PATH_SIZE,
249 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
250 max_header_key_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_SIZE,
251 max_header_value_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_SIZE,
252 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
253 read_timeout_ms: DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS,
254 }
255 }
256}
257
258/// Provides a default value for `Request`.
259///
260/// Returns a new `Request` instance with all fields initialized to their default values.
261impl Default for Request {
262 #[inline(always)]
263 fn default() -> Self {
264 Self {
265 method: Method::default(),
266 host: String::new(),
267 version: HttpVersion::default(),
268 path: String::new(),
269 querys: hash_map_xx_hash3_64(),
270 headers: hash_map_xx_hash3_64(),
271 body: Vec::new(),
272 }
273 }
274}
275
276impl Request {
277 /// Resets the request to its default state while retaining allocated capacity.
278 ///
279 /// This keeps the header map, query map, body, and string allocations so
280 /// persistent (keep-alive) connections avoid repeated allocation per request.
281 ///
282 /// # Returns
283 ///
284 /// - `&mut Self` - A mutable reference to self for chaining.
285 pub fn reset(&mut self) -> &mut Self {
286 self.set_method(Method::default());
287 self.get_mut_host().clear();
288 self.set_version(HttpVersion::default());
289 self.get_mut_path().clear();
290 self.get_mut_querys().clear();
291 self.get_mut_headers().clear();
292 self.get_mut_body().clear();
293 self
294 }
295
296 /// Parses the first line of HTTP request into method, path, and version components.
297 ///
298 /// # Arguments
299 ///
300 /// - `&str` - The first line string of HTTP request to parse.
301 ///
302 /// # Returns
303 ///
304 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>` - A tuple containing:
305 /// - The parsed HTTP method
306 /// - The full path string
307 /// - The parsed HTTP version
308 /// - Or an error if parsing fails
309 #[inline(always)]
310 pub(crate) fn get_http_first_line(
311 line: &str,
312 ) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
313 let mut parts: SplitWhitespace<'_> = line.split_whitespace();
314 let method_str: &str = parts
315 .next()
316 .ok_or(RequestError::HttpRequestPartsInsufficient(
317 HttpStatus::BadRequest,
318 ))?;
319 let full_path: &str = parts
320 .next()
321 .ok_or(RequestError::HttpRequestPartsInsufficient(
322 HttpStatus::BadRequest,
323 ))?;
324 let version_str: &str = parts
325 .next()
326 .ok_or(RequestError::HttpRequestPartsInsufficient(
327 HttpStatus::BadRequest,
328 ))?;
329 let method: RequestMethod = method_str
330 .parse::<RequestMethod>()
331 .unwrap_or(Method::Unknown(method_str.to_string()));
332 let version: RequestVersion = version_str
333 .parse::<RequestVersion>()
334 .unwrap_or(RequestVersion::Unknown(version_str.to_string()));
335 Ok((method, full_path, version))
336 }
337
338 /// Validates the path length against the maximum allowed size.
339 ///
340 /// # Arguments
341 ///
342 /// - `&str` - The path string to check.
343 /// - `usize` - The maximum allowed path size.
344 ///
345 /// # Returns
346 ///
347 /// - `Result<(), RequestError>` - Ok if valid, or an error if the path is too long.
348 #[inline(always)]
349 pub(crate) fn check_http_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
350 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
351 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
352 }
353 Ok(())
354 }
355
356 /// Parses the query string from the full path.
357 ///
358 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
359 /// ensuring proper parsing when both are present.
360 ///
361 /// # Arguments
362 ///
363 /// - `&str` - The full path string containing the query.
364 /// - `Option<usize>` - The index of the query separator (`?`), if present.
365 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
366 ///
367 /// # Returns
368 ///
369 /// - `&str` - The parsed query string slice, or empty string if no query.
370 #[inline(always)]
371 pub(crate) fn get_http_query(
372 path: &str,
373 query_index: Option<usize>,
374 hash_index: Option<usize>,
375 ) -> &str {
376 query_index.map_or(EMPTY_STR, |query_index: usize| {
377 let temp: &str = &path[query_index + 1..];
378 match hash_index {
379 None => temp,
380 Some(hash_index) if hash_index <= query_index => temp,
381 Some(hash_index) => &temp[..hash_index - query_index - 1],
382 }
383 })
384 }
385
386 /// Parses the request path without query string or hash fragment.
387 ///
388 /// # Arguments
389 ///
390 /// - `&str` - The full path string.
391 /// - `Option<usize>` - The index of the query separator (`?`), if present.
392 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
393 ///
394 /// # Returns
395 ///
396 /// - `&str` - The request path slice without query or hash.
397 #[inline(always)]
398 pub(crate) fn get_http_path(
399 path: &str,
400 query_index: Option<usize>,
401 hash_index: Option<usize>,
402 ) -> &str {
403 match query_index.or(hash_index) {
404 Some(separator_index) => &path[..separator_index],
405 None => path,
406 }
407 }
408
409 /// Parses a query string as_ref key-value pairs into the given map.
410 ///
411 /// Expects format "key1=value1&key2=value2". Empty values are allowed.
412 /// The target map is expected to be empty; entries are inserted without
413 /// reallocating the map when it already has sufficient capacity.
414 ///
415 /// # Arguments
416 ///
417 /// - `&str` - The query string to parse.
418 /// - `&mut RequestQuerys` - The map to insert parsed parameters into.
419 #[inline(always)]
420 pub(crate) fn fill_http_querys(query: &str, querys: &mut RequestQuerys) {
421 if query.is_empty() {
422 return;
423 }
424 for pair in query.split(AND) {
425 if let Some((key, value)) = pair.split_once(EQUAL) {
426 if !key.is_empty() {
427 querys.insert(key.to_string(), value.to_string());
428 }
429 } else if !pair.is_empty() {
430 querys.insert(pair.to_string(), String::new());
431 }
432 }
433 }
434
435 /// Checks if the header count exceeds the maximum allowed.
436 ///
437 /// # Arguments
438 ///
439 /// - `usize` - The current number of headers parsed.
440 /// - `usize` - The maximum allowed number of headers.
441 ///
442 /// # Returns
443 ///
444 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
445 #[inline(always)]
446 pub(crate) fn check_http_header_count(
447 count: usize,
448 max_count: usize,
449 ) -> Result<(), RequestError> {
450 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
451 return Err(RequestError::TooManyHeaders(
452 HttpStatus::RequestHeaderFieldsTooLarge,
453 ));
454 }
455 Ok(())
456 }
457
458 /// Checks if a header key exceeds the maximum allowed length.
459 ///
460 /// # Arguments
461 ///
462 /// - `&str` - The header key to check.
463 /// - `usize` - The maximum allowed length for a header key.
464 ///
465 /// # Returns
466 ///
467 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
468 #[inline(always)]
469 pub(crate) fn check_http_header_key_size(
470 key: &str,
471 max_size: usize,
472 ) -> Result<(), RequestError> {
473 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
474 return Err(RequestError::HeaderKeyTooLong(
475 HttpStatus::RequestHeaderFieldsTooLarge,
476 ));
477 }
478 Ok(())
479 }
480
481 /// Checks if a header value exceeds the maximum allowed length.
482 ///
483 /// # Arguments
484 ///
485 /// - `&str` - The header value to check.
486 /// - `usize` - The maximum allowed length for a header value.
487 ///
488 /// # Returns
489 ///
490 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
491 #[inline(always)]
492 pub(crate) fn check_http_header_value_size(
493 value: &str,
494 max_size: usize,
495 ) -> Result<(), RequestError> {
496 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
497 return Err(RequestError::HeaderValueTooLong(
498 HttpStatus::RequestHeaderFieldsTooLarge,
499 ));
500 }
501 Ok(())
502 }
503
504 /// Parses the Content-Length header value and checks it against max body size.
505 ///
506 /// # Arguments
507 ///
508 /// - `&str` - The Content-Length header value string.
509 /// - `usize` - The maximum allowed body size.
510 ///
511 /// # Returns
512 ///
513 /// - `Result<usize, RequestError>` - The parsed content length or an error.
514 #[inline(always)]
515 pub(crate) fn check_http_body_size(
516 value: &str,
517 max_size: usize,
518 ) -> Result<usize, RequestError> {
519 let length: usize = value.parse::<usize>()?;
520 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
521 return Err(RequestError::ContentLengthTooLarge(
522 HttpStatus::PayloadTooLarge,
523 ));
524 }
525 Ok(length)
526 }
527
528 /// Parses HTTP headers from a buffered reader into this request.
529 ///
530 /// This method reads header lines from the provided buffered reader until an empty line
531 /// is encountered, which indicates the end of headers. It checks header count, length,
532 /// and content according to the provided configuration. The request's headers map and
533 /// host string are expected to be empty; they are filled without reallocating when they
534 /// already have sufficient capacity.
535 ///
536 /// # Arguments
537 ///
538 /// - `&mut AsyncBufReadExt + Unpin` - A mutable reference to a buffered reader implementing `AsyncBufReadExt`.
539 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
540 ///
541 /// # Returns
542 ///
543 /// - `Result<usize, RequestError>` - The content length parsed from the
544 /// Content-Length header, or an error if parsing fails.
545 pub(crate) async fn get_http_headers<R>(
546 &mut self,
547 reader: &mut R,
548 config: &RequestConfig,
549 ) -> Result<usize, RequestError>
550 where
551 R: AsyncBufReadExt + Unpin,
552 {
553 let Request { headers, host, .. } = self;
554 let max_header_count: usize = config.get_max_header_count();
555 let max_header_key_size: usize = config.get_max_header_key_size();
556 let max_header_value_size: usize = config.get_max_header_value_size();
557 let max_body_size: usize = config.get_max_body_size();
558 let mut content_size: usize = 0;
559 let mut header_count: usize = 0;
560 let mut header_line_buffer: String = String::with_capacity(HEADER_LINE_BUFFER_CAPACITY);
561 loop {
562 header_line_buffer.clear();
563 AsyncBufReadExt::read_line(reader, &mut header_line_buffer).await?;
564 let header_line: &str = header_line_buffer.trim();
565 if header_line.is_empty() {
566 break;
567 }
568 header_count += 1;
569 Self::check_http_header_count(header_count, max_header_count)?;
570 let (key_part, value_part): (&str, &str) = match header_line.split_once(COLON) {
571 Some(parts) => parts,
572 None => continue,
573 };
574 let key_trimmed: &str = key_part.trim();
575 if key_trimmed.is_empty() {
576 continue;
577 }
578 let key: String = key_trimmed.to_ascii_lowercase();
579 Self::check_http_header_key_size(&key, max_header_key_size)?;
580 let value: &str = value_part.trim();
581 Self::check_http_header_value_size(value, max_header_value_size)?;
582 match key.as_str() {
583 HOST => {
584 host.clear();
585 host.push_str(value);
586 }
587 CONTENT_LENGTH => {
588 content_size = Self::check_http_body_size(value, max_body_size)?;
589 }
590 _ => {}
591 }
592 headers.entry(key).or_default().push_back(value.to_string());
593 }
594 Ok(content_size)
595 }
596
597 /// Reads the request body from the buffered reader into the given buffer.
598 ///
599 /// The target buffer is cleared and resized to the expected content size,
600 /// retaining its allocation when it already has sufficient capacity.
601 ///
602 /// # Arguments
603 ///
604 /// - `&mut AsyncRead + Unpin` - The buffered reader to read from.
605 /// - `&mut RequestBody` - The buffer to read the body bytes into.
606 /// - `usize` - The expected content size.
607 ///
608 /// # Returns
609 ///
610 /// - `Result<(), RequestError>` - Ok on success, or an error if reading fails.
611 #[inline(always)]
612 pub(crate) async fn fill_http_body<R>(
613 reader: &mut R,
614 body: &mut RequestBody,
615 content_size: usize,
616 ) -> Result<(), RequestError>
617 where
618 R: AsyncRead + Unpin,
619 {
620 body.clear();
621 if content_size > 0 {
622 body.resize(content_size, 0);
623 AsyncReadExt::read_exact(reader, body).await?;
624 }
625 Ok(())
626 }
627
628 /// Tries to get a query parameter value by key.
629 ///
630 /// The key type must implement AsRef<str> conversion.
631 ///
632 /// # Arguments
633 ///
634 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
635 ///
636 /// # Returns
637 ///
638 /// - `Option<RequestQuerysValue>` - The parameter value if exists.
639 #[inline(always)]
640 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
641 where
642 K: AsRef<str>,
643 {
644 self.querys.get(key.as_ref()).cloned()
645 }
646
647 /// Gets a query parameter value by key.
648 ///
649 /// The key type must implement AsRef<str> conversion.
650 ///
651 /// # Arguments
652 ///
653 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
654 ///
655 /// # Returns
656 ///
657 /// - `RequestQuerysValue` - The parameter value if exists.
658 ///
659 /// # Panics
660 ///
661 /// This function will panic if the query parameter key is not found.
662 #[inline(always)]
663 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
664 where
665 K: AsRef<str>,
666 {
667 self.try_get_query(key).unwrap()
668 }
669
670 /// Tries to retrieve the value of a request header by its key.
671 ///
672 /// # Arguments
673 ///
674 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
675 ///
676 /// # Returns
677 ///
678 /// - `Option<RequestHeadersValue>` - The optional header values.
679 #[inline(always)]
680 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
681 where
682 K: AsRef<str>,
683 {
684 self.headers.get(key.as_ref()).cloned()
685 }
686
687 /// Retrieves the value of a request header by its key.
688 ///
689 /// # Arguments
690 ///
691 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
692 ///
693 /// # Returns
694 ///
695 /// - `RequestHeadersValue` - The optional header values.
696 ///
697 /// # Panics
698 ///
699 /// This function will panic if the header key is not found.
700 #[inline(always)]
701 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
702 where
703 K: AsRef<str>,
704 {
705 self.try_get_header(key).unwrap()
706 }
707
708 /// Tries to retrieve the first value of a request header by its key.
709 ///
710 /// # Arguments
711 ///
712 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
713 ///
714 /// # Returns
715 ///
716 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
717 #[inline(always)]
718 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
719 where
720 K: AsRef<str>,
721 {
722 self.headers
723 .get(key.as_ref())
724 .and_then(|header_values: &VecDeque<String>| header_values.front().cloned())
725 }
726
727 /// Retrieves the first value of a request header by its key.
728 ///
729 /// # Arguments
730 ///
731 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
732 ///
733 /// # Returns
734 ///
735 /// - `RequestHeadersValueItem` - The first header value if exists.
736 ///
737 /// # Panics
738 ///
739 /// This function will panic if the header key is not found.
740 #[inline(always)]
741 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
742 where
743 K: AsRef<str>,
744 {
745 self.try_get_header_front(key).unwrap()
746 }
747
748 /// Tries to retrieve the last value of a request header by its key.
749 ///
750 /// # Arguments
751 ///
752 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
753 ///
754 /// # Returns
755 ///
756 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
757 #[inline(always)]
758 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
759 where
760 K: AsRef<str>,
761 {
762 self.headers
763 .get(key.as_ref())
764 .and_then(|header_values: &VecDeque<String>| header_values.back().cloned())
765 }
766
767 /// Retrieves the last value of a request header by its key.
768 ///
769 /// # Arguments
770 ///
771 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
772 ///
773 /// # Returns
774 ///
775 /// - `RequestHeadersValueItem` - The last header value if exists.
776 ///
777 /// # Panics
778 ///
779 /// This function will panic if the header key is not found.
780 #[inline(always)]
781 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
782 where
783 K: AsRef<str>,
784 {
785 self.try_get_header_back(key).unwrap()
786 }
787
788 /// Tries to retrieve the number of values for a specific header.
789 ///
790 /// # Arguments
791 ///
792 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
793 ///
794 /// # Returns
795 ///
796 /// - `Option<usize>` - The count of values for the header if exists.
797 #[inline(always)]
798 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
799 where
800 K: AsRef<str>,
801 {
802 self.headers
803 .get(key.as_ref())
804 .map(|header_values: &VecDeque<String>| header_values.len())
805 }
806
807 /// Retrieves the number of values for a specific header.
808 ///
809 /// # Arguments
810 ///
811 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
812 ///
813 /// # Returns
814 ///
815 /// - `usize` - The count of values for the header.
816 ///
817 /// # Panics
818 ///
819 /// This function will panic if the header key is not found.
820 #[inline(always)]
821 pub fn get_header_size<K>(&self, key: K) -> usize
822 where
823 K: AsRef<str>,
824 {
825 self.try_get_header_size(key).unwrap()
826 }
827
828 /// Retrieves the total number of header values across all headers.
829 ///
830 /// # Returns
831 ///
832 /// - `usize` - The total count of all header values.
833 #[inline(always)]
834 pub fn get_headers_values_size(&self) -> usize {
835 self.headers
836 .values()
837 .map(|header_values: &VecDeque<String>| header_values.len())
838 .sum()
839 }
840
841 /// Retrieves the number of unique headers.
842 ///
843 /// # Returns
844 ///
845 /// - `usize` - The count of unique header keys.
846 #[inline(always)]
847 pub fn get_headers_size(&self) -> usize {
848 self.headers.len()
849 }
850
851 /// Checks if a specific header exists.
852 ///
853 /// # Arguments
854 ///
855 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
856 ///
857 /// # Returns
858 ///
859 /// - `bool` - Whether the header exists.
860 #[inline(always)]
861 pub fn has_header<K>(&self, key: K) -> bool
862 where
863 K: AsRef<str>,
864 {
865 self.get_headers().contains_key(key.as_ref())
866 }
867
868 /// Checks if a header contains a specific value.
869 ///
870 /// # Arguments
871 ///
872 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
873 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
874 ///
875 /// # Returns
876 ///
877 /// - `bool` - Whether the header contains the value.
878 #[inline(always)]
879 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
880 where
881 K: AsRef<str>,
882 V: AsRef<str>,
883 {
884 if let Some(values) = self.get_headers().get(key.as_ref()) {
885 values.iter().any(|data: &String| data == value.as_ref())
886 } else {
887 false
888 }
889 }
890
891 /// Tries to parse cookies from the `Cookie` header.
892 ///
893 /// This method retrieves the `Cookie` header value and parses it into
894 /// a collection of key-value pairs representing the cookies.
895 ///
896 /// # Returns
897 ///
898 /// - `Option<Cookies>` - The parsed cookies if the header exists, otherwise `None`.
899 #[inline(always)]
900 pub fn try_get_cookies(&self) -> Option<Cookies> {
901 self.try_get_header_back(COOKIE)
902 .map(|cookie_header: String| Cookie::parse(cookie_header))
903 }
904
905 /// Parses cookies from the `Cookie` header.
906 ///
907 /// This method retrieves the `Cookie` header value and parses it into
908 /// a collection of key-value pairs representing the cookies.
909 ///
910 /// # Returns
911 ///
912 /// - `Cookies` - The parsed cookies.
913 ///
914 /// # Panics
915 ///
916 /// This function will panic if the `Cookie` header is not found.
917 #[inline(always)]
918 pub fn get_cookies(&self) -> Cookies {
919 self.try_get_cookies().unwrap()
920 }
921
922 /// Tries to get a cookie value by its key.
923 ///
924 /// This method first parses the cookies from the `Cookie` header,
925 /// then attempts to retrieve the value for the specified key.
926 ///
927 /// # Arguments
928 ///
929 /// - `AsRef<str>` - The cookie key (implements AsRef<str>).
930 ///
931 /// # Returns
932 ///
933 /// - `Option<CookieValue>` - The cookie value if exists.
934 #[inline(always)]
935 pub fn try_get_cookie<K>(&self, key: K) -> Option<CookieValue>
936 where
937 K: AsRef<str>,
938 {
939 self.try_get_cookies()
940 .and_then(|cookies: Cookies| cookies.get(key.as_ref()).cloned())
941 }
942
943 /// Gets a cookie value by its key.
944 ///
945 /// This method first parses the cookies from the `Cookie` header,
946 /// then retrieves the value for the specified key.
947 ///
948 /// # Arguments
949 ///
950 /// - `AsRef<str>` - The cookie key (implements AsRef<str>).
951 ///
952 /// # Returns
953 ///
954 /// - `CookieValue` - The cookie value.
955 ///
956 /// # Panics
957 ///
958 /// This function will panic if the `Cookie` header is not found
959 /// or the cookie key does not exist.
960 #[inline(always)]
961 pub fn get_cookie<K>(&self, key: K) -> CookieValue
962 where
963 K: AsRef<str>,
964 {
965 self.try_get_cookie(key).unwrap()
966 }
967
968 /// Retrieves the upgrade type from the request headers.
969 ///
970 /// This method looks for the `UPGRADE` header and attempts to parse its value
971 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
972 /// it returns the default `UpgradeType`.
973 ///
974 /// # Returns
975 ///
976 /// - `UpgradeType` - The parsed upgrade type.
977 #[inline(always)]
978 pub fn get_upgrade_type(&self) -> UpgradeType {
979 self.try_get_header_back(UPGRADE)
980 .and_then(|data: String| data.parse::<UpgradeType>().ok())
981 .unwrap_or_default()
982 }
983
984 /// Retrieves the body content of the request as a UTF-8 encoded string.
985 ///
986 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
987 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
988 ///
989 /// # Returns
990 ///
991 /// - `String` - The body content as a string.
992 #[inline(always)]
993 pub fn get_body_string(&self) -> String {
994 String::from_utf8_lossy(self.get_body()).into_owned()
995 }
996
997 /// Deserializes the body content of the request as_ref a specified type `T`.
998 ///
999 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1000 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1001 ///
1002 /// # Arguments
1003 ///
1004 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1005 ///
1006 /// # Returns
1007 ///
1008 /// - `Result<T, serde_json::Error>` - The deserialization result.
1009 #[inline(always)]
1010 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1011 where
1012 T: DeserializeOwned,
1013 {
1014 serde_json::from_slice(self.get_body())
1015 }
1016
1017 /// Deserializes the body content of the request as_ref a specified type `T`.
1018 ///
1019 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1020 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1021 ///
1022 /// # Arguments
1023 ///
1024 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1025 ///
1026 /// # Returns
1027 ///
1028 /// - `T` - The deserialized body content.
1029 ///
1030 /// # Panics
1031 ///
1032 /// This function will panic if the deserialization fails.
1033 #[inline(always)]
1034 pub fn get_body_json<T>(&self) -> T
1035 where
1036 T: DeserializeOwned,
1037 {
1038 self.try_get_body_json().unwrap()
1039 }
1040
1041 /// Checks whether the WebSocket upgrade is enabled for this request.
1042 ///
1043 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1044 ///
1045 /// # Returns
1046 ///
1047 /// - `bool` - Whether WebSocket upgrade is enabled.
1048 #[inline(always)]
1049 pub fn is_ws_upgrade_type(&self) -> bool {
1050 self.get_upgrade_type().is_ws()
1051 }
1052
1053 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1054 ///
1055 /// # Returns
1056 ///
1057 /// - `bool` - Whether the upgrade type is h2c.
1058 #[inline(always)]
1059 pub fn is_h2c_upgrade_type(&self) -> bool {
1060 self.get_upgrade_type().is_h2c()
1061 }
1062
1063 /// Checks if the current upgrade type is TLS (any version).
1064 ///
1065 /// # Returns
1066 ///
1067 /// - `bool` - Whether the upgrade type is TLS.
1068 #[inline(always)]
1069 pub fn is_tls_upgrade_type(&self) -> bool {
1070 self.get_upgrade_type().is_tls()
1071 }
1072
1073 /// Checks whether the upgrade type is unknown.
1074 ///
1075 /// # Returns
1076 ///
1077 /// - `bool` - Whether the upgrade type is unknown.
1078 #[inline(always)]
1079 pub fn is_unknown_upgrade_type(&self) -> bool {
1080 self.get_upgrade_type().is_unknown()
1081 }
1082
1083 /// Determines if a keep-alive connection should be enabled for this request.
1084 ///
1085 /// This function checks the `Connection` header and the HTTP version to determine
1086 /// if keep-alive should be enabled. The logic is as follows:
1087 ///
1088 /// 1. If the `Connection` header exists:
1089 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1090 /// - Returns `false` if the header value is "close" (case-insensitive).
1091 /// 2. If no `Connection` header is present:
1092 /// - Returns `true` if the HTTP version is 1.1 or higher.
1093 /// - Returns `false` otherwise.
1094 ///
1095 /// # Returns
1096 ///
1097 /// - `bool` - Whether keep-alive should be enabled.
1098 #[inline(always)]
1099 pub fn is_enable_keep_alive(&self) -> bool {
1100 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1101 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1102 return true;
1103 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1104 return self.is_ws_upgrade_type();
1105 }
1106 }
1107 self.get_version().is_http1_1_or_higher() || self.is_ws_upgrade_type()
1108 }
1109
1110 /// Determines if keep-alive should be disabled for this request.
1111 ///
1112 /// # Returns
1113 ///
1114 /// - `bool` - Whether keep-alive should be disabled.
1115 #[inline(always)]
1116 pub fn is_disable_keep_alive(&self) -> bool {
1117 !self.is_enable_keep_alive()
1118 }
1119}