http_type/request/impl.rs
1use super::*;
2
3/// Implements the `std::error::Error` trait for `RequestError`.
4impl 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<io::Error> for RequestError {
22 /// Converts an I/O error to a `RequestError`.
23 ///
24 /// # Arguments
25 ///
26 /// - `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: 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 /// - `C` - The configuration, which requires the `AsRef<str>` bound.
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 /// Builds the default `Request` with all fields set to their defaults.
263 #[inline(always)]
264 fn default() -> Self {
265 Self {
266 method: Method::default(),
267 host: String::new(),
268 version: HttpVersion::default(),
269 path: String::new(),
270 querys: hash_map_xx_hash3_64(),
271 headers: hash_map_xx_hash3_64(),
272 body: Vec::new(),
273 }
274 }
275}
276
277impl Request {
278 /// Resets the request to its default state while retaining allocated capacity.
279 ///
280 /// This keeps the header map, query map, body, and string allocations so
281 /// persistent (keep-alive) connections avoid repeated allocation per request.
282 ///
283 /// # Returns
284 ///
285 /// - `&mut Self` - A mutable reference to self for chaining.
286 pub fn reset(&mut self) -> &mut Self {
287 self.set_method(Method::default());
288 self.get_mut_host().clear();
289 self.set_version(HttpVersion::default());
290 self.get_mut_path().clear();
291 self.get_mut_querys().clear();
292 self.get_mut_headers().clear();
293 self.get_mut_body().clear();
294 self
295 }
296
297 /// Parses the first line of HTTP request into method, path, and version components.
298 ///
299 /// # Arguments
300 ///
301 /// - `&str` - The first line string of HTTP request to parse.
302 ///
303 /// # Returns
304 ///
305 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>` - A tuple containing:
306 /// - The parsed HTTP method
307 /// - The full path string
308 /// - The parsed HTTP version
309 /// - Or an error if parsing fails
310 #[inline(always)]
311 pub(crate) fn get_http_first_line(
312 line: &str,
313 ) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
314 let mut parts: SplitWhitespace<'_> = line.split_whitespace();
315 let method_str: &str = parts
316 .next()
317 .ok_or(RequestError::HttpRequestPartsInsufficient(
318 HttpStatus::BadRequest,
319 ))?;
320 let full_path: &str = parts
321 .next()
322 .ok_or(RequestError::HttpRequestPartsInsufficient(
323 HttpStatus::BadRequest,
324 ))?;
325 let version_str: &str = parts
326 .next()
327 .ok_or(RequestError::HttpRequestPartsInsufficient(
328 HttpStatus::BadRequest,
329 ))?;
330 let method: RequestMethod = method_str
331 .parse::<RequestMethod>()
332 .unwrap_or(Method::Unknown(method_str.to_string()));
333 let version: RequestVersion = version_str
334 .parse::<RequestVersion>()
335 .unwrap_or(RequestVersion::Unknown(version_str.to_string()));
336 Ok((method, full_path, version))
337 }
338
339 /// Validates the path length against the maximum allowed size.
340 ///
341 /// # Arguments
342 ///
343 /// - `&str` - The path string to check.
344 /// - `usize` - The maximum allowed path size.
345 ///
346 /// # Returns
347 ///
348 /// - `Result<(), RequestError>` - Ok if valid, or an error if the path is too long.
349 #[inline(always)]
350 pub(crate) fn check_http_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
351 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
352 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
353 }
354 Ok(())
355 }
356
357 /// Parses the query string from the full path.
358 ///
359 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
360 /// ensuring proper parsing when both are present.
361 ///
362 /// # Arguments
363 ///
364 /// - `&str` - The full path string containing the query.
365 /// - `Option<usize>` - The index of the query separator (`?`), if present.
366 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
367 ///
368 /// # Returns
369 ///
370 /// - `&str` - The parsed query string slice, or empty string if no query.
371 #[inline(always)]
372 pub(crate) fn get_http_query(
373 path: &str,
374 query_index: Option<usize>,
375 hash_index: Option<usize>,
376 ) -> &str {
377 query_index.map_or(EMPTY_STR, |query_index: usize| {
378 let temp: &str = &path[query_index + 1..];
379 match hash_index {
380 None => temp,
381 Some(hash_index) if hash_index <= query_index => temp,
382 Some(hash_index) => &temp[..hash_index - query_index - 1],
383 }
384 })
385 }
386
387 /// Parses the request path without query string or hash fragment.
388 ///
389 /// # Arguments
390 ///
391 /// - `&str` - The full path string.
392 /// - `Option<usize>` - The index of the query separator (`?`), if present.
393 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
394 ///
395 /// # Returns
396 ///
397 /// - `&str` - The request path slice without query or hash.
398 #[inline(always)]
399 pub(crate) fn get_http_path(
400 path: &str,
401 query_index: Option<usize>,
402 hash_index: Option<usize>,
403 ) -> &str {
404 match query_index.or(hash_index) {
405 Some(separator_index) => &path[..separator_index],
406 None => path,
407 }
408 }
409
410 /// Parses a query string as_ref key-value pairs into the given map.
411 ///
412 /// Expects format "key1=value1&key2=value2". Empty values are allowed, and a
413 /// key that repeats keeps every value instead of letting the last one win.
414 /// The target map is expected to be empty; entries are inserted without
415 /// reallocating the map when it already has sufficient capacity.
416 ///
417 /// # Arguments
418 ///
419 /// - `&str` - The query string to parse.
420 /// - `&mut RequestQuerys` - The map to insert parsed parameters into.
421 #[inline(always)]
422 pub(crate) fn fill_http_querys(query: &str, querys: &mut RequestQuerys) {
423 if query.is_empty() {
424 return;
425 }
426 for pair in query.split(AND) {
427 if let Some((key, value)) = pair.split_once(EQUAL) {
428 if !key.is_empty() {
429 querys
430 .entry(key.to_string())
431 .or_default()
432 .push_back(value.to_string());
433 }
434 } else if !pair.is_empty() {
435 querys.entry(pair.to_string()).or_default();
436 }
437 }
438 }
439
440 /// Checks if the header count exceeds the maximum allowed.
441 ///
442 /// # Arguments
443 ///
444 /// - `usize` - The current number of headers parsed.
445 /// - `usize` - The maximum allowed number of headers.
446 ///
447 /// # Returns
448 ///
449 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
450 #[inline(always)]
451 pub(crate) fn check_http_header_count(
452 count: usize,
453 max_count: usize,
454 ) -> Result<(), RequestError> {
455 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
456 return Err(RequestError::TooManyHeaders(
457 HttpStatus::RequestHeaderFieldsTooLarge,
458 ));
459 }
460 Ok(())
461 }
462
463 /// Checks if a header key exceeds the maximum allowed length.
464 ///
465 /// # Arguments
466 ///
467 /// - `&str` - The header key to check.
468 /// - `usize` - The maximum allowed length for a header key.
469 ///
470 /// # Returns
471 ///
472 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
473 #[inline(always)]
474 pub(crate) fn check_http_header_key_size(
475 key: &str,
476 max_size: usize,
477 ) -> Result<(), RequestError> {
478 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
479 return Err(RequestError::HeaderKeyTooLong(
480 HttpStatus::RequestHeaderFieldsTooLarge,
481 ));
482 }
483 Ok(())
484 }
485
486 /// Checks if a header value exceeds the maximum allowed length.
487 ///
488 /// # Arguments
489 ///
490 /// - `&str` - The header value to check.
491 /// - `usize` - The maximum allowed length for a header value.
492 ///
493 /// # Returns
494 ///
495 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
496 #[inline(always)]
497 pub(crate) fn check_http_header_value_size(
498 value: &str,
499 max_size: usize,
500 ) -> Result<(), RequestError> {
501 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
502 return Err(RequestError::HeaderValueTooLong(
503 HttpStatus::RequestHeaderFieldsTooLarge,
504 ));
505 }
506 Ok(())
507 }
508
509 /// Parses the Content-Length header value and checks it against max body size.
510 ///
511 /// # Arguments
512 ///
513 /// - `&str` - The Content-Length header value string.
514 /// - `usize` - The maximum allowed body size.
515 ///
516 /// # Returns
517 ///
518 /// - `Result<usize, RequestError>` - The parsed content length or an error.
519 #[inline(always)]
520 pub(crate) fn check_http_body_size(
521 value: &str,
522 max_size: usize,
523 ) -> Result<usize, RequestError> {
524 let length: usize = value.parse::<usize>()?;
525 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
526 return Err(RequestError::ContentLengthTooLarge(
527 HttpStatus::PayloadTooLarge,
528 ));
529 }
530 Ok(length)
531 }
532
533 /// Parses HTTP headers from a buffered reader into this request.
534 ///
535 /// This method reads header lines from the provided buffered reader until an empty line
536 /// is encountered, which indicates the end of headers. It checks header count, length,
537 /// and content according to the provided configuration. The request's headers map and
538 /// host string are expected to be empty; they are filled without reallocating when they
539 /// already have sufficient capacity.
540 ///
541 /// # Arguments
542 ///
543 /// - `&mut R` - A mutable reference to a buffered reader, which requires the
544 /// `AsyncBufReadExt + Unpin` bound.
545 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
546 ///
547 /// # Returns
548 ///
549 /// - `Result<usize, RequestError>` - The content length parsed from the
550 /// Content-Length header, or an error if parsing fails.
551 pub(crate) async fn get_http_headers<R>(
552 &mut self,
553 reader: &mut R,
554 config: &RequestConfig,
555 ) -> Result<usize, RequestError>
556 where
557 R: AsyncBufReadExt + Unpin,
558 {
559 let Request { headers, host, .. } = self;
560 let max_header_count: usize = config.get_max_header_count();
561 let max_header_key_size: usize = config.get_max_header_key_size();
562 let max_header_value_size: usize = config.get_max_header_value_size();
563 let max_body_size: usize = config.get_max_body_size();
564 let mut content_size: usize = 0;
565 let mut header_count: usize = 0;
566 let mut header_line_buffer: String = String::with_capacity(HEADER_LINE_BUFFER_CAPACITY);
567 loop {
568 header_line_buffer.clear();
569 AsyncBufReadExt::read_line(reader, &mut header_line_buffer).await?;
570 let header_line: &str = header_line_buffer.trim();
571 if header_line.is_empty() {
572 break;
573 }
574 header_count += 1;
575 Self::check_http_header_count(header_count, max_header_count)?;
576 let (key_part, value_part): (&str, &str) = match header_line.split_once(COLON) {
577 Some(parts) => parts,
578 None => continue,
579 };
580 let key_trimmed: &str = key_part.trim();
581 if key_trimmed.is_empty() {
582 continue;
583 }
584 let key: String = key_trimmed.to_ascii_lowercase();
585 Self::check_http_header_key_size(&key, max_header_key_size)?;
586 let value: &str = value_part.trim();
587 Self::check_http_header_value_size(value, max_header_value_size)?;
588 match key.as_str() {
589 HOST => {
590 host.clear();
591 host.push_str(value);
592 }
593 CONTENT_LENGTH => {
594 content_size = Self::check_http_body_size(value, max_body_size)?;
595 }
596 _ => {}
597 }
598 headers.entry(key).or_default().push_back(value.to_string());
599 }
600 Ok(content_size)
601 }
602
603 /// Reads the request body from the buffered reader into the given buffer.
604 ///
605 /// The target buffer is cleared and resized to the expected content size,
606 /// retaining its allocation when it already has sufficient capacity.
607 ///
608 /// # Arguments
609 ///
610 /// - `&mut R` - The buffered reader to read from, which requires the `AsyncRead + Unpin` bound.
611 /// - `&mut RequestBody` - The buffer to read the body bytes into.
612 /// - `usize` - The expected content size.
613 ///
614 /// # Returns
615 ///
616 /// - `Result<(), RequestError>` - Ok on success, or an error if reading fails.
617 #[inline(always)]
618 pub(crate) async fn fill_http_body<R>(
619 reader: &mut R,
620 body: &mut RequestBody,
621 content_size: usize,
622 ) -> Result<(), RequestError>
623 where
624 R: AsyncRead + Unpin,
625 {
626 body.clear();
627 if content_size > 0 {
628 body.resize(content_size, 0);
629 AsyncReadExt::read_exact(reader, body).await?;
630 }
631 Ok(())
632 }
633
634 /// Tries to get a query parameter by key.
635 ///
636 /// The key type must implement AsRef<str> conversion. A key that repeats in
637 /// the query carries every one of its values.
638 ///
639 /// # Arguments
640 ///
641 /// - `K` - The query parameter key, which implements `AsRef<str>`.
642 ///
643 /// # Returns
644 ///
645 /// - `Option<RequestQuerysValue>` - Every value of the parameter if it exists.
646 #[inline(always)]
647 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
648 where
649 K: AsRef<str>,
650 {
651 self.get_querys().get(key.as_ref()).cloned()
652 }
653
654 /// Tries to get the first query parameter value by key.
655 ///
656 /// Use this when the parameter is expected to appear once; use
657 /// `try_get_query` when every value matters.
658 ///
659 /// # Arguments
660 ///
661 /// - `K` - The query parameter key, which implements `AsRef<str>`.
662 ///
663 /// # Returns
664 ///
665 /// - `Option<RequestQuerysValueItem>` - The first parameter value if it exists.
666 #[inline(always)]
667 pub fn try_get_query_front<K>(&self, key: K) -> Option<RequestQuerysValueItem>
668 where
669 K: AsRef<str>,
670 {
671 self.get_querys()
672 .get(key.as_ref())
673 .and_then(|values: &VecDeque<String>| values.front().cloned())
674 }
675
676 /// Tries to get the last query parameter value by key.
677 ///
678 /// # Arguments
679 ///
680 /// - `K` - The query parameter key, which implements `AsRef<str>`.
681 ///
682 /// # Returns
683 ///
684 /// - `Option<RequestQuerysValueItem>` - The last parameter value if it exists.
685 #[inline(always)]
686 pub fn try_get_query_back<K>(&self, key: K) -> Option<RequestQuerysValueItem>
687 where
688 K: AsRef<str>,
689 {
690 self.get_querys()
691 .get(key.as_ref())
692 .and_then(|values: &VecDeque<String>| values.back().cloned())
693 }
694
695 /// Tries to get the number of values of a query parameter.
696 ///
697 /// # Arguments
698 ///
699 /// - `K` - The query parameter key, which implements `AsRef<str>`.
700 ///
701 /// # Returns
702 ///
703 /// - `Option<usize>` - The number of values if the parameter exists.
704 #[inline(always)]
705 pub fn try_get_query_size<K>(&self, key: K) -> Option<usize>
706 where
707 K: AsRef<str>,
708 {
709 self.get_querys()
710 .get(key.as_ref())
711 .map(|values: &VecDeque<String>| values.len())
712 }
713
714 /// Checks whether a query parameter exists.
715 ///
716 /// # Arguments
717 ///
718 /// - `K` - The query parameter key, which implements `AsRef<str>`.
719 ///
720 /// # Returns
721 ///
722 /// - `bool` - Whether the parameter exists.
723 #[inline(always)]
724 pub fn has_query<K>(&self, key: K) -> bool
725 where
726 K: AsRef<str>,
727 {
728 self.get_querys().contains_key(key.as_ref())
729 }
730
731 /// Gets a query parameter by key.
732 ///
733 /// # Arguments
734 ///
735 /// - `K` - The query parameter key, which implements `AsRef<str>`.
736 ///
737 /// # Returns
738 ///
739 /// - `RequestQuerysValue` - Every value of the parameter.
740 ///
741 /// # Panics
742 ///
743 /// This function will panic if the query parameter key is not found.
744 #[inline(always)]
745 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
746 where
747 K: AsRef<str>,
748 {
749 self.try_get_query(key).unwrap()
750 }
751
752 /// Gets the first query parameter value by key.
753 ///
754 /// # Arguments
755 ///
756 /// - `K` - The query parameter key, which implements `AsRef<str>`.
757 ///
758 /// # Returns
759 ///
760 /// - `RequestQuerysValueItem` - The first parameter value.
761 ///
762 /// # Panics
763 ///
764 /// This function will panic if the query parameter key is not found.
765 #[inline(always)]
766 pub fn get_query_front<K>(&self, key: K) -> RequestQuerysValueItem
767 where
768 K: AsRef<str>,
769 {
770 self.try_get_query_front(key).unwrap()
771 }
772
773 /// Retrieves the number of query parameters.
774 ///
775 /// # Returns
776 ///
777 /// - `usize` - The count of distinct query parameter keys.
778 #[inline(always)]
779 pub fn get_querys_size(&self) -> usize {
780 self.get_querys().len()
781 }
782
783 /// Tries to retrieve the value of a request header by its key.
784 ///
785 /// The key is matched case-insensitively, because the parser stores every
786 /// header name lowercased and an HTTP header name is case-insensitive by
787 /// specification. Looking a header up with `Content-Type` and with
788 /// `content-type` therefore find the same value.
789 ///
790 /// # Arguments
791 ///
792 /// - `K` - The header's key, which must implement `AsRef<str>`.
793 ///
794 /// # Returns
795 ///
796 /// - `Option<RequestHeadersValue>` - The optional header values.
797 #[inline(always)]
798 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
799 where
800 K: AsRef<str>,
801 {
802 self.get_headers()
803 .get(&key.as_ref().to_ascii_lowercase())
804 .cloned()
805 }
806
807 /// Retrieves the value of a request header by its key.
808 ///
809 /// # Arguments
810 ///
811 /// - `K` - The header's key, which must implement `AsRef<str>`.
812 ///
813 /// # Returns
814 ///
815 /// - `RequestHeadersValue` - The optional header values.
816 ///
817 /// # Panics
818 ///
819 /// This function will panic if the header key is not found.
820 #[inline(always)]
821 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
822 where
823 K: AsRef<str>,
824 {
825 self.try_get_header(key).unwrap()
826 }
827
828 /// Tries to retrieve the first value of a request header by its key.
829 ///
830 /// # Arguments
831 ///
832 /// - `K` - The header's key, which must implement `AsRef<str>`.
833 ///
834 /// # Returns
835 ///
836 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
837 #[inline(always)]
838 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
839 where
840 K: AsRef<str>,
841 {
842 self.get_headers()
843 .get(&key.as_ref().to_ascii_lowercase())
844 .and_then(|header_values: &VecDeque<String>| header_values.front().cloned())
845 }
846
847 /// Retrieves the first value of a request header by its key.
848 ///
849 /// # Arguments
850 ///
851 /// - `K` - The header's key, which must implement `AsRef<str>`.
852 ///
853 /// # Returns
854 ///
855 /// - `RequestHeadersValueItem` - The first header value if exists.
856 ///
857 /// # Panics
858 ///
859 /// This function will panic if the header key is not found.
860 #[inline(always)]
861 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
862 where
863 K: AsRef<str>,
864 {
865 self.try_get_header_front(key).unwrap()
866 }
867
868 /// Tries to retrieve the last value of a request header by its key.
869 ///
870 /// # Arguments
871 ///
872 /// - `K` - The header's key, which must implement `AsRef<str>`.
873 ///
874 /// # Returns
875 ///
876 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
877 #[inline(always)]
878 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
879 where
880 K: AsRef<str>,
881 {
882 self.get_headers()
883 .get(&key.as_ref().to_ascii_lowercase())
884 .and_then(|header_values: &VecDeque<String>| header_values.back().cloned())
885 }
886
887 /// Retrieves the last value of a request header by its key.
888 ///
889 /// # Arguments
890 ///
891 /// - `K` - The header's key, which must implement `AsRef<str>`.
892 ///
893 /// # Returns
894 ///
895 /// - `RequestHeadersValueItem` - The last header value if exists.
896 ///
897 /// # Panics
898 ///
899 /// This function will panic if the header key is not found.
900 #[inline(always)]
901 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
902 where
903 K: AsRef<str>,
904 {
905 self.try_get_header_back(key).unwrap()
906 }
907
908 /// Tries to retrieve the number of values for a specific header.
909 ///
910 /// # Arguments
911 ///
912 /// - `K` - The header's key, which must implement `AsRef<str>`.
913 ///
914 /// # Returns
915 ///
916 /// - `Option<usize>` - The count of values for the header if exists.
917 #[inline(always)]
918 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
919 where
920 K: AsRef<str>,
921 {
922 self.get_headers()
923 .get(&key.as_ref().to_ascii_lowercase())
924 .map(|header_values: &VecDeque<String>| header_values.len())
925 }
926
927 /// Retrieves the number of values for a specific header.
928 ///
929 /// # Arguments
930 ///
931 /// - `K` - The header's key, which must implement `AsRef<str>`.
932 ///
933 /// # Returns
934 ///
935 /// - `usize` - The count of values for the header.
936 ///
937 /// # Panics
938 ///
939 /// This function will panic if the header key is not found.
940 #[inline(always)]
941 pub fn get_header_size<K>(&self, key: K) -> usize
942 where
943 K: AsRef<str>,
944 {
945 self.try_get_header_size(key).unwrap()
946 }
947
948 /// Retrieves the total number of header values across all headers.
949 ///
950 /// # Returns
951 ///
952 /// - `usize` - The total count of all header values.
953 #[inline(always)]
954 pub fn get_headers_values_size(&self) -> usize {
955 self.get_headers()
956 .values()
957 .map(|header_values: &VecDeque<String>| header_values.len())
958 .sum()
959 }
960
961 /// Retrieves the number of unique headers.
962 ///
963 /// # Returns
964 ///
965 /// - `usize` - The count of unique header keys.
966 #[inline(always)]
967 pub fn get_headers_size(&self) -> usize {
968 self.get_headers().len()
969 }
970
971 /// Checks if a specific header exists.
972 ///
973 /// # Arguments
974 ///
975 /// - `K` - The header key to check, which must implement `AsRef<str>`.
976 ///
977 /// # Returns
978 ///
979 /// - `bool` - Whether the header exists.
980 #[inline(always)]
981 pub fn has_header<K>(&self, key: K) -> bool
982 where
983 K: AsRef<str>,
984 {
985 self.get_headers()
986 .contains_key(&key.as_ref().to_ascii_lowercase())
987 }
988
989 /// Checks if a header contains a specific value.
990 ///
991 /// # Arguments
992 ///
993 /// - `K` - The header key to check, which must implement `AsRef<str>`.
994 /// - `V` - The value to search for, which must implement `AsRef<str>`.
995 ///
996 /// # Returns
997 ///
998 /// - `bool` - Whether the header contains the value.
999 #[inline(always)]
1000 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
1001 where
1002 K: AsRef<str>,
1003 V: AsRef<str>,
1004 {
1005 if let Some(values) = self.get_headers().get(&key.as_ref().to_ascii_lowercase()) {
1006 values.iter().any(|data: &String| data == value.as_ref())
1007 } else {
1008 false
1009 }
1010 }
1011
1012 /// Tries to parse cookies from the `Cookie` header.
1013 ///
1014 /// This method retrieves the `Cookie` header value and parses it into
1015 /// a collection of key-value pairs representing the cookies.
1016 ///
1017 /// # Returns
1018 ///
1019 /// - `Option<Cookies>` - The parsed cookies if the header exists, otherwise `None`.
1020 #[inline(always)]
1021 pub fn try_get_cookies(&self) -> Option<Cookies> {
1022 self.try_get_header_back(COOKIE)
1023 .map(|cookie_header: String| Cookie::parse(cookie_header))
1024 }
1025
1026 /// Parses cookies from the `Cookie` header.
1027 ///
1028 /// This method retrieves the `Cookie` header value and parses it into
1029 /// a collection of key-value pairs representing the cookies.
1030 ///
1031 /// # Returns
1032 ///
1033 /// - `Cookies` - The parsed cookies.
1034 ///
1035 /// # Panics
1036 ///
1037 /// This function will panic if the `Cookie` header is not found.
1038 #[inline(always)]
1039 pub fn get_cookies(&self) -> Cookies {
1040 self.try_get_cookies().unwrap()
1041 }
1042
1043 /// Tries to get a cookie value by its key.
1044 ///
1045 /// This method first parses the cookies from the `Cookie` header,
1046 /// then attempts to retrieve the value for the specified key.
1047 ///
1048 /// # Arguments
1049 ///
1050 /// - `K` - The cookie key, which implements `AsRef<str>`.
1051 ///
1052 /// # Returns
1053 ///
1054 /// - `Option<CookieValue>` - The cookie value if exists.
1055 #[inline(always)]
1056 pub fn try_get_cookie<K>(&self, key: K) -> Option<CookieValue>
1057 where
1058 K: AsRef<str>,
1059 {
1060 self.try_get_cookies()
1061 .and_then(|cookies: Cookies| cookies.get(key.as_ref()).cloned())
1062 }
1063
1064 /// Gets a cookie value by its key.
1065 ///
1066 /// This method first parses the cookies from the `Cookie` header,
1067 /// then retrieves the value for the specified key.
1068 ///
1069 /// # Arguments
1070 ///
1071 /// - `K` - The cookie key, which implements `AsRef<str>`.
1072 ///
1073 /// # Returns
1074 ///
1075 /// - `CookieValue` - The cookie value.
1076 ///
1077 /// # Panics
1078 ///
1079 /// This function will panic if the `Cookie` header is not found
1080 /// or the cookie key does not exist.
1081 #[inline(always)]
1082 pub fn get_cookie<K>(&self, key: K) -> CookieValue
1083 where
1084 K: AsRef<str>,
1085 {
1086 self.try_get_cookie(key).unwrap()
1087 }
1088
1089 /// Retrieves the upgrade type from the request headers.
1090 ///
1091 /// This method looks for the `UPGRADE` header and attempts to parse its value
1092 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
1093 /// it returns the default `UpgradeType`.
1094 ///
1095 /// # Returns
1096 ///
1097 /// - `UpgradeType` - The parsed upgrade type.
1098 #[inline(always)]
1099 pub fn get_upgrade_type(&self) -> UpgradeType {
1100 self.try_get_header_back(UPGRADE)
1101 .and_then(|data: String| data.parse::<UpgradeType>().ok())
1102 .unwrap_or_default()
1103 }
1104
1105 /// Retrieves the body content of the request as a UTF-8 encoded string.
1106 ///
1107 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
1108 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
1109 ///
1110 /// # Returns
1111 ///
1112 /// - `String` - The body content as a string.
1113 #[inline(always)]
1114 pub fn get_body_string(&self) -> String {
1115 String::from_utf8_lossy(self.get_body()).into_owned()
1116 }
1117
1118 /// Deserializes the body content of the request as_ref a specified type `T`.
1119 ///
1120 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1121 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1122 ///
1123 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1124 ///
1125 /// # Returns
1126 ///
1127 /// - `Result<T, serde_json::Error>` - The deserialization result.
1128 #[inline(always)]
1129 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1130 where
1131 T: DeserializeOwned,
1132 {
1133 serde_json::from_slice(self.get_body())
1134 }
1135
1136 /// Deserializes the body content of the request as_ref a specified type `T`.
1137 ///
1138 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1139 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1140 ///
1141 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1142 ///
1143 /// # Returns
1144 ///
1145 /// - `T` - The deserialized body content.
1146 ///
1147 /// # Panics
1148 ///
1149 /// This function will panic if the deserialization fails.
1150 #[inline(always)]
1151 pub fn get_body_json<T>(&self) -> T
1152 where
1153 T: DeserializeOwned,
1154 {
1155 self.try_get_body_json().unwrap()
1156 }
1157
1158 /// Checks whether the WebSocket upgrade is enabled for this request.
1159 ///
1160 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1161 ///
1162 /// # Returns
1163 ///
1164 /// - `bool` - Whether WebSocket upgrade is enabled.
1165 #[inline(always)]
1166 pub fn is_ws_upgrade_type(&self) -> bool {
1167 self.get_upgrade_type().is_ws()
1168 }
1169
1170 /// Checks whether the request declares a `multipart/form-data` body.
1171 ///
1172 /// # Returns
1173 ///
1174 /// - `bool` - Whether the request content type is `multipart/form-data`.
1175 #[inline(always)]
1176 pub fn is_multipart_form_data(&self) -> bool {
1177 self.try_get_content_type()
1178 .map(|content_type: String| MultipartFormData::is_form_data(content_type))
1179 .unwrap_or(false)
1180 }
1181
1182 /// Tries to get the request content type with its parameters stripped.
1183 ///
1184 /// A `Content-Type` header such as `text/html; charset=utf-8` yields the
1185 /// media type alone, so a caller comparing against a media type does not
1186 /// have to know that parameters may follow it.
1187 ///
1188 /// # Returns
1189 ///
1190 /// - `Option<RequestContentType>` - The media type, or `None` when the header is absent.
1191 #[inline(always)]
1192 pub fn try_get_content_type(&self) -> Option<RequestContentType> {
1193 self.try_get_header_front(CONTENT_TYPE)
1194 .map(|value: String| {
1195 value
1196 .split(SEMICOLON)
1197 .next()
1198 .unwrap_or(EMPTY_STR)
1199 .trim()
1200 .to_ascii_lowercase()
1201 })
1202 }
1203
1204 /// Tries to get one parameter of the request `Content-Type` header.
1205 ///
1206 /// The name is matched case-insensitively and a quoted value is unquoted,
1207 /// so both `boundary=abc` and `boundary="abc"` yield `abc`.
1208 ///
1209 /// # Arguments
1210 ///
1211 /// - `K` - The parameter name, which requires the `AsRef<str>` bound.
1212 ///
1213 /// # Returns
1214 ///
1215 /// - `Option<RequestContentTypeParameter>` - The parameter value, or `None` when absent.
1216 pub fn try_get_content_type_parameter<K>(&self, name: K) -> Option<RequestContentTypeParameter>
1217 where
1218 K: AsRef<str>,
1219 {
1220 let content_type: String = self.try_get_header_front(CONTENT_TYPE)?;
1221 let name: &str = name.as_ref();
1222 for parameter in content_type.split(SEMICOLON).skip(1) {
1223 let (key, value) = parameter.trim().split_once(EQUAL)?;
1224 if !key.trim().eq_ignore_ascii_case(name) {
1225 continue;
1226 }
1227 let value: &str = value.trim();
1228 let value: &str = value
1229 .strip_prefix(MULTIPART_PARAMETER_QUOTE)
1230 .and_then(|value: &str| value.strip_suffix(MULTIPART_PARAMETER_QUOTE))
1231 .unwrap_or(value);
1232 if !value.is_empty() {
1233 return Some(value.to_string());
1234 }
1235 }
1236 None
1237 }
1238
1239 /// Tries to decode a `multipart/form-data` body into its parts.
1240 ///
1241 /// The boundary is read from the request `Content-Type` header rather than
1242 /// guessed, so a body whose content type declares no boundary, a truncated
1243 /// body, and a part without a name all yield `None`.
1244 ///
1245 /// # Returns
1246 ///
1247 /// - `Option<MultipartFormDataParts>` - The decoded parts, or `None` when unavailable.
1248 pub fn try_get_body_form_data(&self) -> Option<MultipartFormDataParts> {
1249 let boundary: MultipartFormDataBoundary =
1250 self.try_get_content_type_parameter(MULTIPART_BOUNDARY_PARAMETER)?;
1251 MultipartFormData::parse(self.get_body(), &boundary)
1252 }
1253
1254 /// Decodes an `application/x-www-form-urlencoded` body into its fields.
1255 ///
1256 /// # Returns
1257 ///
1258 /// - `BodyForm` - The decoded form fields.
1259 #[inline(always)]
1260 pub fn get_body_form(&self) -> BodyForm {
1261 MultipartFormData::parse_url_encoded(self.get_body())
1262 }
1263
1264 /// Tries to get a plain text field of a `multipart/form-data` body.
1265 ///
1266 /// A part that uploads a file is skipped, so a file field never silently
1267 /// decodes as text.
1268 ///
1269 /// # Arguments
1270 ///
1271 /// - `K` - The form field name, which requires the `AsRef<str>` bound.
1272 ///
1273 /// # Returns
1274 ///
1275 /// - `Option<BodyFormValue>` - The field value, or `None` when absent or a file.
1276 pub fn try_get_body_form_data_text<K>(&self, name: K) -> Option<BodyFormValue>
1277 where
1278 K: AsRef<str>,
1279 {
1280 let parts: MultipartFormDataParts = self.try_get_body_form_data()?;
1281 MultipartFormData::try_get_part_text(&parts, name)
1282 }
1283
1284 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1285 ///
1286 /// # Returns
1287 ///
1288 /// - `bool` - Whether the upgrade type is h2c.
1289 #[inline(always)]
1290 pub fn is_h2c_upgrade_type(&self) -> bool {
1291 self.get_upgrade_type().is_h2c()
1292 }
1293
1294 /// Checks if the current upgrade type is TLS (any version).
1295 ///
1296 /// # Returns
1297 ///
1298 /// - `bool` - Whether the upgrade type is TLS.
1299 #[inline(always)]
1300 pub fn is_tls_upgrade_type(&self) -> bool {
1301 self.get_upgrade_type().is_tls()
1302 }
1303
1304 /// Checks whether the upgrade type is unknown.
1305 ///
1306 /// # Returns
1307 ///
1308 /// - `bool` - Whether the upgrade type is unknown.
1309 #[inline(always)]
1310 pub fn is_unknown_upgrade_type(&self) -> bool {
1311 self.get_upgrade_type().is_unknown()
1312 }
1313
1314 /// Determines if a keep-alive connection should be enabled for this request.
1315 ///
1316 /// This function checks the `Connection` header and the HTTP version to determine
1317 /// if keep-alive should be enabled. The logic is as follows:
1318 ///
1319 /// 1. If the `Connection` header exists:
1320 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1321 /// - Returns `false` if the header value is "close" (case-insensitive).
1322 /// 2. If no `Connection` header is present:
1323 /// - Returns `true` if the HTTP version is 1.1 or higher.
1324 /// - Returns `false` otherwise.
1325 ///
1326 /// # Returns
1327 ///
1328 /// - `bool` - Whether keep-alive should be enabled.
1329 #[inline(always)]
1330 pub fn is_enable_keep_alive(&self) -> bool {
1331 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1332 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1333 return true;
1334 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1335 return self.is_ws_upgrade_type();
1336 }
1337 }
1338 self.get_version().is_http1_1_or_higher() || self.is_ws_upgrade_type()
1339 }
1340
1341 /// Determines if keep-alive should be disabled for this request.
1342 ///
1343 /// # Returns
1344 ///
1345 /// - `bool` - Whether keep-alive should be disabled.
1346 #[inline(always)]
1347 pub fn is_disable_keep_alive(&self) -> bool {
1348 !self.is_enable_keep_alive()
1349 }
1350}