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
98/// Inherent implementation of [`RequestError`].
99impl RequestError {
100 /// Gets the HTTP status associated with this error.
101 ///
102 /// Returns the HttpStatus enum variant that corresponds to this error.
103 ///
104 /// # Returns
105 ///
106 /// - `HttpStatus` - The HTTP status associated with this error.
107 pub fn get_http_status(&self) -> HttpStatus {
108 match self {
109 Self::HttpRead(status) => *status,
110 Self::GetTcpStream(status) => *status,
111 Self::GetTlsStream(status) => *status,
112 Self::ReadConnection(status) => *status,
113 Self::RequestAborted(status) => *status,
114 Self::TlsStreamConnect(status) => *status,
115 Self::NeedOpenRedirect(status) => *status,
116 Self::MaxRedirectTimes(status) => *status,
117 Self::MethodsNotSupport(status) => *status,
118 Self::RedirectInvalidUrl(status) => *status,
119 Self::ClientDisconnected(status) => *status,
120 Self::RedirectUrlDeadLoop(status) => *status,
121 Self::ClientClosedConnection(status) => *status,
122 Self::ServerClosedConnection(status) => *status,
123 Self::IncompleteWebSocketFrame(status) => *status,
124 Self::RequestTooLong(status) => *status,
125 Self::PathTooLong(status) => *status,
126 Self::QueryTooLong(status) => *status,
127 Self::HeaderLineTooLong(status) => *status,
128 Self::TooManyHeaders(status) => *status,
129 Self::HeaderKeyTooLong(status) => *status,
130 Self::HeaderValueTooLong(status) => *status,
131 Self::ContentLengthTooLarge(status) => *status,
132 Self::InvalidContentLength(status) => *status,
133 Self::InvalidUrlScheme(status) => *status,
134 Self::InvalidUrlHost(status) => *status,
135 Self::InvalidUrlPort(status) => *status,
136 Self::InvalidUrlPath(status) => *status,
137 Self::InvalidUrlQuery(status) => *status,
138 Self::InvalidUrlFragment(status) => *status,
139 Self::ReadTimeout(status) => *status,
140 Self::WriteTimeout(status) => *status,
141 Self::TcpConnectionFailed(status) => *status,
142 Self::TlsHandshakeFailed(status) => *status,
143 Self::TlsCertificateInvalid(status) => *status,
144 Self::WebSocketFrameTooLarge(status) => *status,
145 Self::WebSocketOpcodeUnsupported(status) => *status,
146 Self::WebSocketMaskMissing(status) => *status,
147 Self::WebSocketPayloadCorrupted(status) => *status,
148 Self::WebSocketInvalidUtf8(status) => *status,
149 Self::WebSocketInvalidCloseCode(status) => *status,
150 Self::WebSocketInvalidExtension(status) => *status,
151 Self::HttpRequestPartsInsufficient(status) => *status,
152 Self::TcpStreamConnect(status) => *status,
153 Self::TlsConnectorBuild(status) => *status,
154 Self::InvalidUrl(status) => *status,
155 Self::ConfigReadError(status) => *status,
156 Self::TcpStreamConnectString(status) => *status,
157 Self::TlsConnectorBuildString(status) => *status,
158 Self::Request(_) => HttpStatus::BadRequest,
159 Self::Unknown(status) => *status,
160 }
161 }
162
163 /// Gets the numeric HTTP status code associated with this error.
164 ///
165 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
166 ///
167 /// # Returns
168 ///
169 /// - `ResponseStatusCode` - The numeric HTTP status code.
170 pub fn get_http_status_code(&self) -> ResponseStatusCode {
171 self.get_http_status().code()
172 }
173}
174
175/// Implementation of `Default` trait for `RequestConfig`.
176impl Default for RequestConfig {
177 /// Creates a new `RequestConfig` with default secure settings.
178 ///
179 /// This constructor initializes the configuration with standard security limits
180 /// suitable for most HTTP request parsing scenarios.
181 ///
182 /// # Returns
183 ///
184 /// - `Self` - A new `RequestConfig` instance with default settings.
185 #[inline(always)]
186 fn default() -> Self {
187 Self {
188 buffer_size: DEFAULT_BUFFER_SIZE,
189 max_path_size: DEFAULT_MAX_PATH_SIZE,
190 max_header_count: DEFAULT_MAX_HEADER_COUNT,
191 max_header_key_size: DEFAULT_MAX_HEADER_KEY_SIZE,
192 max_header_value_size: DEFAULT_MAX_HEADER_VALUE_SIZE,
193 max_body_size: DEFAULT_MAX_BODY_SIZE,
194 read_timeout_ms: DEFAULT_READ_TIMEOUT_MS,
195 }
196 }
197}
198
199/// Inherent implementation of [`RequestConfig`].
200impl RequestConfig {
201 /// Creates a new `RequestConfig` from a JSON string.
202 ///
203 /// # Arguments
204 ///
205 /// - `C` - The configuration, which requires the `AsRef<str>` bound.
206 ///
207 /// # Returns
208 ///
209 /// - `Result<RequestConfig, serde_json::Error>` - The parsed `RequestConfig` or an error.
210 pub fn from_json<C>(json: C) -> Result<RequestConfig, serde_json::Error>
211 where
212 C: AsRef<str>,
213 {
214 serde_json::from_str(json.as_ref())
215 }
216
217 /// Creates a new `RequestConfig` with low-security settings.
218 ///
219 /// This constructor initializes the configuration with less restrictive limits
220 /// for environments where higher limits are needed.
221 ///
222 /// # Returns
223 ///
224 /// - `Self` - A new `RequestConfig` instance with low-security settings.
225 #[inline(always)]
226 pub fn low_security() -> Self {
227 Self {
228 buffer_size: DEFAULT_LOW_SECURITY_BUFFER_SIZE,
229 max_path_size: DEFAULT_LOW_SECURITY_MAX_PATH_SIZE,
230 max_header_count: DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT,
231 max_header_key_size: DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE,
232 max_header_value_size: DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE,
233 max_body_size: DEFAULT_LOW_SECURITY_MAX_BODY_SIZE,
234 read_timeout_ms: DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS,
235 }
236 }
237
238 /// Creates a new `RequestConfig` with high-security settings.
239 ///
240 /// This constructor initializes the configuration with more restrictive limits
241 /// to provide maximum protection against various attacks in high-risk environments.
242 ///
243 /// # Returns
244 ///
245 /// - `Self` - A new `RequestConfig` instance with high-security settings.
246 #[inline(always)]
247 pub fn high_security() -> Self {
248 Self {
249 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
250 max_path_size: DEFAULT_HIGH_SECURITY_MAX_PATH_SIZE,
251 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
252 max_header_key_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_SIZE,
253 max_header_value_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_SIZE,
254 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
255 read_timeout_ms: DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS,
256 }
257 }
258}
259
260/// Provides a default value for `Request`.
261///
262/// Returns a new `Request` instance with all fields initialized to their default values.
263impl Default for Request {
264 /// Builds the default `Request` with all fields set to their defaults.
265 #[inline(always)]
266 fn default() -> Self {
267 Self {
268 method: Method::default(),
269 host: String::new(),
270 version: HttpVersion::default(),
271 path: String::new(),
272 querys: hash_map_xx_hash3_64(),
273 headers: hash_map_xx_hash3_64(),
274 body: Vec::new(),
275 }
276 }
277}
278
279/// Inherent implementation of [`Request`].
280impl Request {
281 /// Resets the request to its default state while retaining allocated capacity.
282 ///
283 /// This keeps the header map, query map, body, and string allocations so
284 /// persistent (keep-alive) connections avoid repeated allocation per request.
285 ///
286 /// # Returns
287 ///
288 /// - `&mut Self` - A mutable reference to self for chaining.
289 pub fn reset(&mut self) -> &mut Self {
290 self.set_method(Method::default());
291 self.get_mut_host().clear();
292 self.set_version(HttpVersion::default());
293 self.get_mut_path().clear();
294 self.get_mut_querys().clear();
295 self.recycle_headers();
296 self.get_mut_body().clear();
297 self
298 }
299
300 /// Hands the header entries to the pool and empties the header map.
301 ///
302 /// The map ends up empty, exactly as clearing it would, but the name and
303 /// the value buffers of every header survive in the pool. The next
304 /// request on the same connection takes them back and overwrites them,
305 /// so a connection that keeps its headers stops allocating for them.
306 ///
307 /// # Returns
308 ///
309 /// - `()` - The headers have been recycled.
310 fn recycle_headers(&mut self) {
311 let headers: &mut RequestHeaders = self.get_mut_headers();
312 if headers.is_empty() {
313 return;
314 }
315 for (key, values) in headers.drain() {
316 return_header_entry((key, values));
317 }
318 }
319
320 /// Parses the first line of HTTP request into method, path, and version components.
321 ///
322 /// # Arguments
323 ///
324 /// - `&str` - The first line string of HTTP request to parse.
325 ///
326 /// # Returns
327 ///
328 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>` - A tuple containing:
329 /// - The parsed HTTP method
330 /// - The full path string
331 /// - The parsed HTTP version
332 /// - Or an error if parsing fails
333 #[inline(always)]
334 pub(crate) fn get_http_first_line(
335 line: &str,
336 ) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
337 let mut parts: SplitWhitespace<'_> = line.split_whitespace();
338 let method_str: &str = parts
339 .next()
340 .ok_or(RequestError::HttpRequestPartsInsufficient(
341 HttpStatus::BadRequest,
342 ))?;
343 let full_path: &str = parts
344 .next()
345 .ok_or(RequestError::HttpRequestPartsInsufficient(
346 HttpStatus::BadRequest,
347 ))?;
348 let version_str: &str = parts
349 .next()
350 .ok_or(RequestError::HttpRequestPartsInsufficient(
351 HttpStatus::BadRequest,
352 ))?;
353 if parts.next().is_some() {
354 return Err(RequestError::HttpRequestPartsInsufficient(
355 HttpStatus::BadRequest,
356 ));
357 }
358 let method: RequestMethod = method_str
359 .parse::<RequestMethod>()
360 .unwrap_or(Method::Unknown(method_str.to_string()));
361 let version: RequestVersion = match version_str.parse::<RequestVersion>() {
362 Ok(RequestVersion::Unknown(_)) | Err(_) => {
363 return Err(RequestError::HttpRequestPartsInsufficient(
364 HttpStatus::BadRequest,
365 ));
366 }
367 Ok(version) => version,
368 };
369 Ok((method, full_path, version))
370 }
371
372 /// Validates the path length against the maximum allowed size.
373 ///
374 /// # Arguments
375 ///
376 /// - `&str` - The path string to check.
377 /// - `usize` - The maximum allowed path size.
378 ///
379 /// # Returns
380 ///
381 /// - `Result<(), RequestError>` - Ok if valid, or an error if the path is too long.
382 #[inline(always)]
383 pub(crate) fn check_http_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
384 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
385 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
386 }
387 Ok(())
388 }
389
390 /// Parses the query string from the full path.
391 ///
392 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
393 /// ensuring proper parsing when both are present.
394 ///
395 /// # Arguments
396 ///
397 /// - `&str` - The full path string containing the query.
398 /// - `Option<usize>` - The index of the query separator (`?`), if present.
399 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
400 ///
401 /// # Returns
402 ///
403 /// - `&str` - The parsed query string slice, or empty string if no query.
404 #[inline(always)]
405 pub(crate) fn get_http_query(
406 path: &str,
407 query_index: Option<usize>,
408 hash_index: Option<usize>,
409 ) -> &str {
410 query_index.map_or(EMPTY_STR, |query_index: usize| {
411 let temp: &str = &path[query_index + 1..];
412 match hash_index {
413 None => temp,
414 Some(hash_index) if hash_index <= query_index => temp,
415 Some(hash_index) => &temp[..hash_index - query_index - 1],
416 }
417 })
418 }
419
420 /// Parses the request path without query string or hash fragment.
421 ///
422 /// # Arguments
423 ///
424 /// - `&str` - The full path string.
425 /// - `Option<usize>` - The index of the query separator (`?`), if present.
426 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
427 ///
428 /// # Returns
429 ///
430 /// - `&str` - The request path slice without query or hash.
431 #[inline(always)]
432 pub(crate) fn get_http_path(
433 path: &str,
434 query_index: Option<usize>,
435 hash_index: Option<usize>,
436 ) -> &str {
437 match query_index.or(hash_index) {
438 Some(separator_index) => &path[..separator_index],
439 None => path,
440 }
441 }
442
443 /// Parses a query string as_ref key-value pairs into the given map.
444 ///
445 /// Expects format "key1=value1&key2=value2". Empty values are allowed, and a
446 /// key that repeats keeps every value instead of letting the last one win.
447 /// The target map is expected to be empty; entries are inserted without
448 /// reallocating the map when it already has sufficient capacity.
449 ///
450 /// # Arguments
451 ///
452 /// - `&str` - The query string to parse.
453 /// - `&mut RequestQuerys` - The map to insert parsed parameters into.
454 #[inline(always)]
455 pub(crate) fn fill_http_querys(query: &str, querys: &mut RequestQuerys) {
456 if query.is_empty() {
457 return;
458 }
459 for pair in query.split(AND) {
460 if let Some((key, value)) = pair.split_once(EQUAL) {
461 if !key.is_empty() {
462 querys
463 .entry(key.to_string())
464 .or_default()
465 .push_back(value.to_string());
466 }
467 } else if !pair.is_empty() {
468 querys.entry(pair.to_string()).or_default();
469 }
470 }
471 }
472
473 /// Checks if the header count exceeds the maximum allowed.
474 ///
475 /// # Arguments
476 ///
477 /// - `usize` - The current number of headers parsed.
478 /// - `usize` - The maximum allowed number of headers.
479 ///
480 /// # Returns
481 ///
482 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
483 #[inline(always)]
484 pub(crate) fn check_http_header_count(
485 count: usize,
486 max_count: usize,
487 ) -> Result<(), RequestError> {
488 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
489 return Err(RequestError::TooManyHeaders(
490 HttpStatus::RequestHeaderFieldsTooLarge,
491 ));
492 }
493 Ok(())
494 }
495
496 /// Checks if a header key exceeds the maximum allowed length.
497 ///
498 /// # Arguments
499 ///
500 /// - `&str` - The header key to check.
501 /// - `usize` - The maximum allowed length for a header key.
502 ///
503 /// # Returns
504 ///
505 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
506 #[inline(always)]
507 pub(crate) fn check_http_header_key_size(
508 key: &str,
509 max_size: usize,
510 ) -> Result<(), RequestError> {
511 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
512 return Err(RequestError::HeaderKeyTooLong(
513 HttpStatus::RequestHeaderFieldsTooLarge,
514 ));
515 }
516 Ok(())
517 }
518
519 /// Checks if a header value exceeds the maximum allowed length.
520 ///
521 /// # Arguments
522 ///
523 /// - `&str` - The header value to check.
524 /// - `usize` - The maximum allowed length for a header value.
525 ///
526 /// # Returns
527 ///
528 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
529 #[inline(always)]
530 pub(crate) fn check_http_header_value_size(
531 value: &str,
532 max_size: usize,
533 ) -> Result<(), RequestError> {
534 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
535 return Err(RequestError::HeaderValueTooLong(
536 HttpStatus::RequestHeaderFieldsTooLarge,
537 ));
538 }
539 Ok(())
540 }
541
542 /// Parses the Content-Length header value and checks it against max body size.
543 ///
544 /// # Arguments
545 ///
546 /// - `&str` - The Content-Length header value string.
547 /// - `usize` - The maximum allowed body size.
548 ///
549 /// # Returns
550 ///
551 /// - `Result<usize, RequestError>` - The parsed content length or an error.
552 #[inline(always)]
553 pub(crate) fn check_http_body_size(
554 value: &str,
555 max_size: usize,
556 ) -> Result<usize, RequestError> {
557 if value.is_empty() || !value.bytes().all(|byte: u8| byte.is_ascii_digit()) {
558 return Err(RequestError::InvalidContentLength(HttpStatus::BadRequest));
559 }
560 let length: usize = value.parse::<usize>()?;
561 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
562 return Err(RequestError::ContentLengthTooLarge(
563 HttpStatus::PayloadTooLarge,
564 ));
565 }
566 Ok(length)
567 }
568
569 /// Parses HTTP headers from a buffered reader into this request.
570 ///
571 /// This method reads header lines from the provided buffered reader until an empty line
572 /// is encountered, which indicates the end of headers. It checks header count, length,
573 /// and content according to the provided configuration. The request's headers map and
574 /// host string are expected to be empty; they are filled without reallocating when they
575 /// already have sufficient capacity.
576 ///
577 /// The line buffer belongs to the caller so that a keep-alive connection
578 /// reads every header line of every request into the same allocation.
579 ///
580 /// # Arguments
581 ///
582 /// - `&mut R` - A mutable reference to a buffered reader, which requires the
583 /// `AsyncBufReadExt + Unpin` bound.
584 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
585 /// - `&mut String` - The buffer the header lines are read into.
586 ///
587 /// # Returns
588 ///
589 /// - `Result<usize, RequestError>` - The content length parsed from the
590 /// Content-Length header, or an error if parsing fails.
591 pub(crate) async fn get_http_headers<R>(
592 &mut self,
593 reader: &mut R,
594 config: &RequestConfig,
595 header_line_buffer: &mut String,
596 ) -> Result<usize, RequestError>
597 where
598 R: AsyncBufReadExt + Unpin,
599 {
600 let Request {
601 headers,
602 host,
603 version,
604 ..
605 } = self;
606 let max_header_count: usize = config.get_max_header_count();
607 let max_header_key_size: usize = config.get_max_header_key_size();
608 let max_header_value_size: usize = config.get_max_header_value_size();
609 let max_body_size: usize = config.get_max_body_size();
610 let mut content_size: usize = 0;
611 let mut header_count: usize = 0;
612 let mut content_length_seen: bool = false;
613 let mut host_seen: bool = false;
614 loop {
615 header_line_buffer.clear();
616 AsyncBufReadExt::read_line(reader, header_line_buffer).await?;
617 let header_line: &str = header_line_buffer
618 .strip_suffix(HTTP_HEADER_LINE_FEED)
619 .ok_or(RequestError::HttpRead(HttpStatus::BadRequest))?;
620 let header_line: &str = header_line
621 .strip_suffix(HTTP_HEADER_CARRIAGE_RETURN)
622 .unwrap_or(header_line);
623 if header_line.is_empty() {
624 break;
625 }
626 if header_line.starts_with(HTTP_HEADER_OPTIONAL_WHITESPACE) {
627 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
628 }
629 header_count += 1;
630 Self::check_http_header_count(header_count, max_header_count)?;
631 let (key, value_part): (&str, &str) = header_line
632 .split_once(COLON)
633 .ok_or(RequestError::HttpRead(HttpStatus::BadRequest))?;
634 let valid_key: bool = key.bytes().all(|byte: u8| {
635 byte.is_ascii_alphanumeric() || HTTP_HEADER_TOKEN_PUNCTUATION.contains(&byte)
636 });
637 if key.is_empty() || !valid_key {
638 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
639 }
640 Self::check_http_header_key_size(key, max_header_key_size)?;
641 if value_part.bytes().any(|byte: u8| {
642 (byte < HTTP_HEADER_CONTROL_LIMIT && byte != HTTP_HEADER_TAB)
643 || byte == HTTP_HEADER_DELETE
644 }) {
645 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
646 }
647 let value: &str = value_part.trim_matches(HTTP_HEADER_OPTIONAL_WHITESPACE);
648 Self::check_http_header_value_size(value, max_header_value_size)?;
649 match key {
650 key if key.eq_ignore_ascii_case(HTTP_HEADER_TRANSFER_ENCODING) => {
651 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
652 }
653 key if key.eq_ignore_ascii_case(HOST) => {
654 if host_seen {
655 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
656 }
657 host_seen = true;
658 host.clear();
659 host.push_str(value);
660 }
661 key if key.eq_ignore_ascii_case(CONTENT_LENGTH) => {
662 if content_length_seen {
663 return Err(RequestError::InvalidContentLength(HttpStatus::BadRequest));
664 }
665 content_length_seen = true;
666 content_size = Self::check_http_body_size(value, max_body_size)?;
667 }
668 _ => {}
669 }
670 Self::insert_http_header(headers, key, value);
671 }
672 if *version == HTTP_HOST_REQUIRED_VERSION && !host_seen {
673 return Err(RequestError::HttpRead(HttpStatus::BadRequest));
674 }
675 Ok(content_size)
676 }
677
678 /// Stores one header, reusing a pooled name and value where possible.
679 ///
680 /// The name is lowercased into the buffer of a recycled entry and the
681 /// value is written into that entry's value buffer, so a header that was
682 /// already seen on this connection costs no allocation at all.
683 ///
684 /// # Arguments
685 ///
686 /// - `&mut RequestHeaders` - The header map to store the header in.
687 /// - `&str` - The header name, as it arrived.
688 /// - `&str` - The header value.
689 fn insert_http_header(headers: &mut RequestHeaders, key: &str, value: &str) {
690 let (mut name, mut values): (String, VecDeque<String>) =
691 take_header_entry().unwrap_or_else(|| (String::new(), VecDeque::new()));
692 name.clear();
693 name.push_str(key);
694 name.make_ascii_lowercase();
695 match headers.entry(name) {
696 Entry::Occupied(mut occupied) => {
697 // The header repeats: it keeps every value it was given.
698 occupied.get_mut().push_back(value.to_string());
699 return_header_entry((String::new(), values));
700 }
701 Entry::Vacant(vacant) => {
702 // A recycled entry may carry the values of a header that was
703 // sent more than once. Those values belong to that header, so
704 // only the first one is kept and the rest are dropped.
705 while values.len() > 1 {
706 values.pop_back();
707 }
708 if values.is_empty() {
709 values.push_back(String::new());
710 }
711 if let Some(slot) = values.front_mut() {
712 slot.clear();
713 slot.push_str(value);
714 }
715 vacant.insert(values);
716 }
717 }
718 }
719
720 /// Reads the request body from the buffered reader into the given buffer.
721 ///
722 /// The target buffer is cleared and resized to the expected content size,
723 /// retaining its allocation when it already has sufficient capacity.
724 ///
725 /// # Arguments
726 ///
727 /// - `&mut R` - The buffered reader to read from, which requires the `AsyncRead + Unpin` bound.
728 /// - `&mut RequestBody` - The buffer to read the body bytes into.
729 /// - `usize` - The expected content size.
730 ///
731 /// # Returns
732 ///
733 /// - `Result<(), RequestError>` - Ok on success, or an error if reading fails.
734 #[inline(always)]
735 pub(crate) async fn fill_http_body<R>(
736 reader: &mut R,
737 body: &mut RequestBody,
738 content_size: usize,
739 ) -> Result<(), RequestError>
740 where
741 R: AsyncRead + Unpin,
742 {
743 body.clear();
744 if content_size > 0 {
745 body.resize(content_size, 0);
746 AsyncReadExt::read_exact(reader, body).await?;
747 }
748 Ok(())
749 }
750
751 /// Tries to get a query parameter by key.
752 ///
753 /// The key type must implement AsRef<str> conversion. A key that repeats in
754 /// the query carries every one of its values.
755 ///
756 /// # Arguments
757 ///
758 /// - `K` - The query parameter key, which implements `AsRef<str>`.
759 ///
760 /// # Returns
761 ///
762 /// - `Option<RequestQuerysValue>` - Every value of the parameter if it exists.
763 #[inline(always)]
764 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
765 where
766 K: AsRef<str>,
767 {
768 self.get_querys().get(key.as_ref()).cloned()
769 }
770
771 /// Tries to get the first query parameter value by key.
772 ///
773 /// Use this when the parameter is expected to appear once; use
774 /// `try_get_query` when every value matters.
775 ///
776 /// # Arguments
777 ///
778 /// - `K` - The query parameter key, which implements `AsRef<str>`.
779 ///
780 /// # Returns
781 ///
782 /// - `Option<RequestQuerysValueItem>` - The first parameter value if it exists.
783 #[inline(always)]
784 pub fn try_get_query_front<K>(&self, key: K) -> Option<RequestQuerysValueItem>
785 where
786 K: AsRef<str>,
787 {
788 self.get_querys()
789 .get(key.as_ref())
790 .and_then(|values: &VecDeque<String>| values.front().cloned())
791 }
792
793 /// Tries to get the last query parameter value by key.
794 ///
795 /// # Arguments
796 ///
797 /// - `K` - The query parameter key, which implements `AsRef<str>`.
798 ///
799 /// # Returns
800 ///
801 /// - `Option<RequestQuerysValueItem>` - The last parameter value if it exists.
802 #[inline(always)]
803 pub fn try_get_query_back<K>(&self, key: K) -> Option<RequestQuerysValueItem>
804 where
805 K: AsRef<str>,
806 {
807 self.get_querys()
808 .get(key.as_ref())
809 .and_then(|values: &VecDeque<String>| values.back().cloned())
810 }
811
812 /// Tries to get the number of values of a query parameter.
813 ///
814 /// # Arguments
815 ///
816 /// - `K` - The query parameter key, which implements `AsRef<str>`.
817 ///
818 /// # Returns
819 ///
820 /// - `Option<usize>` - The number of values if the parameter exists.
821 #[inline(always)]
822 pub fn try_get_query_size<K>(&self, key: K) -> Option<usize>
823 where
824 K: AsRef<str>,
825 {
826 self.get_querys()
827 .get(key.as_ref())
828 .map(|values: &VecDeque<String>| values.len())
829 }
830
831 /// Checks whether a query parameter exists.
832 ///
833 /// # Arguments
834 ///
835 /// - `K` - The query parameter key, which implements `AsRef<str>`.
836 ///
837 /// # Returns
838 ///
839 /// - `bool` - Whether the parameter exists.
840 #[inline(always)]
841 pub fn has_query<K>(&self, key: K) -> bool
842 where
843 K: AsRef<str>,
844 {
845 self.get_querys().contains_key(key.as_ref())
846 }
847
848 /// Gets a query parameter by key.
849 ///
850 /// # Arguments
851 ///
852 /// - `K` - The query parameter key, which implements `AsRef<str>`.
853 ///
854 /// # Returns
855 ///
856 /// - `RequestQuerysValue` - Every value of the parameter.
857 ///
858 /// # Panics
859 ///
860 /// This function will panic if the query parameter key is not found.
861 #[inline(always)]
862 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
863 where
864 K: AsRef<str>,
865 {
866 self.try_get_query(key).unwrap()
867 }
868
869 /// Gets the first query parameter value by key.
870 ///
871 /// # Arguments
872 ///
873 /// - `K` - The query parameter key, which implements `AsRef<str>`.
874 ///
875 /// # Returns
876 ///
877 /// - `RequestQuerysValueItem` - The first parameter value.
878 ///
879 /// # Panics
880 ///
881 /// This function will panic if the query parameter key is not found.
882 #[inline(always)]
883 pub fn get_query_front<K>(&self, key: K) -> RequestQuerysValueItem
884 where
885 K: AsRef<str>,
886 {
887 self.try_get_query_front(key).unwrap()
888 }
889
890 /// Retrieves the number of query parameters.
891 ///
892 /// # Returns
893 ///
894 /// - `usize` - The count of distinct query parameter keys.
895 #[inline(always)]
896 pub fn get_querys_size(&self) -> usize {
897 self.get_querys().len()
898 }
899
900 /// Tries to retrieve the value of a request header by its key.
901 ///
902 /// The key is matched case-insensitively, because the parser stores every
903 /// header name lowercased and an HTTP header name is case-insensitive by
904 /// specification. Looking a header up with `Content-Type` and with
905 /// `content-type` therefore find the same value.
906 ///
907 /// # Arguments
908 ///
909 /// - `K` - The header's key, which must implement `AsRef<str>`.
910 ///
911 /// # Returns
912 ///
913 /// - `Option<RequestHeadersValue>` - The optional header values.
914 #[inline(always)]
915 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
916 where
917 K: AsRef<str>,
918 {
919 self.get_headers()
920 .get(&key.as_ref().to_ascii_lowercase())
921 .cloned()
922 }
923
924 /// Retrieves the value of a request header by its key.
925 ///
926 /// # Arguments
927 ///
928 /// - `K` - The header's key, which must implement `AsRef<str>`.
929 ///
930 /// # Returns
931 ///
932 /// - `RequestHeadersValue` - The optional header values.
933 ///
934 /// # Panics
935 ///
936 /// This function will panic if the header key is not found.
937 #[inline(always)]
938 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
939 where
940 K: AsRef<str>,
941 {
942 self.try_get_header(key).unwrap()
943 }
944
945 /// Tries to retrieve the first value of a request header by its key.
946 ///
947 /// # Arguments
948 ///
949 /// - `K` - The header's key, which must implement `AsRef<str>`.
950 ///
951 /// # Returns
952 ///
953 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
954 #[inline(always)]
955 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
956 where
957 K: AsRef<str>,
958 {
959 self.get_headers()
960 .get(&key.as_ref().to_ascii_lowercase())
961 .and_then(|header_values: &VecDeque<String>| header_values.front().cloned())
962 }
963
964 /// Retrieves the first value of a request header by its key.
965 ///
966 /// # Arguments
967 ///
968 /// - `K` - The header's key, which must implement `AsRef<str>`.
969 ///
970 /// # Returns
971 ///
972 /// - `RequestHeadersValueItem` - The first header value if exists.
973 ///
974 /// # Panics
975 ///
976 /// This function will panic if the header key is not found.
977 #[inline(always)]
978 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
979 where
980 K: AsRef<str>,
981 {
982 self.try_get_header_front(key).unwrap()
983 }
984
985 /// Tries to retrieve the last value of a request header by its key.
986 ///
987 /// # Arguments
988 ///
989 /// - `K` - The header's key, which must implement `AsRef<str>`.
990 ///
991 /// # Returns
992 ///
993 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
994 #[inline(always)]
995 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
996 where
997 K: AsRef<str>,
998 {
999 self.get_headers()
1000 .get(&key.as_ref().to_ascii_lowercase())
1001 .and_then(|header_values: &VecDeque<String>| header_values.back().cloned())
1002 }
1003
1004 /// Retrieves the last value of a request header by its key.
1005 ///
1006 /// # Arguments
1007 ///
1008 /// - `K` - The header's key, which must implement `AsRef<str>`.
1009 ///
1010 /// # Returns
1011 ///
1012 /// - `RequestHeadersValueItem` - The last header value if exists.
1013 ///
1014 /// # Panics
1015 ///
1016 /// This function will panic if the header key is not found.
1017 #[inline(always)]
1018 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
1019 where
1020 K: AsRef<str>,
1021 {
1022 self.try_get_header_back(key).unwrap()
1023 }
1024
1025 /// Tries to retrieve the number of values for a specific header.
1026 ///
1027 /// # Arguments
1028 ///
1029 /// - `K` - The header's key, which must implement `AsRef<str>`.
1030 ///
1031 /// # Returns
1032 ///
1033 /// - `Option<usize>` - The count of values for the header if exists.
1034 #[inline(always)]
1035 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
1036 where
1037 K: AsRef<str>,
1038 {
1039 self.get_headers()
1040 .get(&key.as_ref().to_ascii_lowercase())
1041 .map(|header_values: &VecDeque<String>| header_values.len())
1042 }
1043
1044 /// Retrieves the number of values for a specific header.
1045 ///
1046 /// # Arguments
1047 ///
1048 /// - `K` - The header's key, which must implement `AsRef<str>`.
1049 ///
1050 /// # Returns
1051 ///
1052 /// - `usize` - The count of values for the header.
1053 ///
1054 /// # Panics
1055 ///
1056 /// This function will panic if the header key is not found.
1057 #[inline(always)]
1058 pub fn get_header_size<K>(&self, key: K) -> usize
1059 where
1060 K: AsRef<str>,
1061 {
1062 self.try_get_header_size(key).unwrap()
1063 }
1064
1065 /// Retrieves the total number of header values across all headers.
1066 ///
1067 /// # Returns
1068 ///
1069 /// - `usize` - The total count of all header values.
1070 #[inline(always)]
1071 pub fn get_headers_values_size(&self) -> usize {
1072 self.get_headers()
1073 .values()
1074 .map(|header_values: &VecDeque<String>| header_values.len())
1075 .sum()
1076 }
1077
1078 /// Retrieves the number of unique headers.
1079 ///
1080 /// # Returns
1081 ///
1082 /// - `usize` - The count of unique header keys.
1083 #[inline(always)]
1084 pub fn get_headers_size(&self) -> usize {
1085 self.get_headers().len()
1086 }
1087
1088 /// Checks if a specific header exists.
1089 ///
1090 /// # Arguments
1091 ///
1092 /// - `K` - The header key to check, which must implement `AsRef<str>`.
1093 ///
1094 /// # Returns
1095 ///
1096 /// - `bool` - Whether the header exists.
1097 #[inline(always)]
1098 pub fn has_header<K>(&self, key: K) -> bool
1099 where
1100 K: AsRef<str>,
1101 {
1102 self.get_headers()
1103 .contains_key(&key.as_ref().to_ascii_lowercase())
1104 }
1105
1106 /// Checks if a header contains a specific value.
1107 ///
1108 /// # Arguments
1109 ///
1110 /// - `K` - The header key to check, which must implement `AsRef<str>`.
1111 /// - `V` - The value to search for, which must implement `AsRef<str>`.
1112 ///
1113 /// # Returns
1114 ///
1115 /// - `bool` - Whether the header contains the value.
1116 #[inline(always)]
1117 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
1118 where
1119 K: AsRef<str>,
1120 V: AsRef<str>,
1121 {
1122 if let Some(values) = self.get_headers().get(&key.as_ref().to_ascii_lowercase()) {
1123 values.iter().any(|data: &String| data == value.as_ref())
1124 } else {
1125 false
1126 }
1127 }
1128
1129 /// Tries to parse cookies from the `Cookie` header.
1130 ///
1131 /// This method retrieves the `Cookie` header value and parses it into
1132 /// a collection of key-value pairs representing the cookies.
1133 ///
1134 /// # Returns
1135 ///
1136 /// - `Option<Cookies>` - The parsed cookies if the header exists, otherwise `None`.
1137 #[inline(always)]
1138 pub fn try_get_cookies(&self) -> Option<Cookies> {
1139 self.try_get_header_back(COOKIE)
1140 .map(|cookie_header: String| Cookie::parse(cookie_header))
1141 }
1142
1143 /// Parses cookies from the `Cookie` header.
1144 ///
1145 /// This method retrieves the `Cookie` header value and parses it into
1146 /// a collection of key-value pairs representing the cookies.
1147 ///
1148 /// # Returns
1149 ///
1150 /// - `Cookies` - The parsed cookies.
1151 ///
1152 /// # Panics
1153 ///
1154 /// This function will panic if the `Cookie` header is not found.
1155 #[inline(always)]
1156 pub fn get_cookies(&self) -> Cookies {
1157 self.try_get_cookies().unwrap()
1158 }
1159
1160 /// Tries to get a cookie value by its key.
1161 ///
1162 /// This method first parses the cookies from the `Cookie` header,
1163 /// then attempts to retrieve the value for the specified key.
1164 ///
1165 /// # Arguments
1166 ///
1167 /// - `K` - The cookie key, which implements `AsRef<str>`.
1168 ///
1169 /// # Returns
1170 ///
1171 /// - `Option<CookieValue>` - The cookie value if exists.
1172 #[inline(always)]
1173 pub fn try_get_cookie<K>(&self, key: K) -> Option<CookieValue>
1174 where
1175 K: AsRef<str>,
1176 {
1177 self.try_get_cookies()
1178 .and_then(|cookies: Cookies| cookies.get(key.as_ref()).cloned())
1179 }
1180
1181 /// Gets a cookie value by its key.
1182 ///
1183 /// This method first parses the cookies from the `Cookie` header,
1184 /// then retrieves the value for the specified key.
1185 ///
1186 /// # Arguments
1187 ///
1188 /// - `K` - The cookie key, which implements `AsRef<str>`.
1189 ///
1190 /// # Returns
1191 ///
1192 /// - `CookieValue` - The cookie value.
1193 ///
1194 /// # Panics
1195 ///
1196 /// This function will panic if the `Cookie` header is not found
1197 /// or the cookie key does not exist.
1198 #[inline(always)]
1199 pub fn get_cookie<K>(&self, key: K) -> CookieValue
1200 where
1201 K: AsRef<str>,
1202 {
1203 self.try_get_cookie(key).unwrap()
1204 }
1205
1206 /// Retrieves the upgrade type from the request headers.
1207 ///
1208 /// This method looks for the `UPGRADE` header and attempts to parse its value
1209 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
1210 /// it returns the default `UpgradeType`.
1211 ///
1212 /// # Returns
1213 ///
1214 /// - `UpgradeType` - The parsed upgrade type.
1215 #[inline(always)]
1216 pub fn get_upgrade_type(&self) -> UpgradeType {
1217 self.try_get_header_back(UPGRADE)
1218 .and_then(|data: String| data.parse::<UpgradeType>().ok())
1219 .unwrap_or_default()
1220 }
1221
1222 /// Retrieves the body content of the request as a UTF-8 encoded string.
1223 ///
1224 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
1225 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
1226 ///
1227 /// # Returns
1228 ///
1229 /// - `String` - The body content as a string.
1230 #[inline(always)]
1231 pub fn get_body_string(&self) -> String {
1232 String::from_utf8_lossy(self.get_body()).into_owned()
1233 }
1234
1235 /// Deserializes the body content of the request as_ref a specified type `T`.
1236 ///
1237 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1238 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1239 ///
1240 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1241 ///
1242 /// # Returns
1243 ///
1244 /// - `Result<T, serde_json::Error>` - The deserialization result.
1245 #[inline(always)]
1246 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1247 where
1248 T: DeserializeOwned,
1249 {
1250 serde_json::from_slice(self.get_body())
1251 }
1252
1253 /// Deserializes the body content of the request as_ref a specified type `T`.
1254 ///
1255 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1256 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1257 ///
1258 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1259 ///
1260 /// # Returns
1261 ///
1262 /// - `T` - The deserialized body content.
1263 ///
1264 /// # Panics
1265 ///
1266 /// This function will panic if the deserialization fails.
1267 #[inline(always)]
1268 pub fn get_body_json<T>(&self) -> T
1269 where
1270 T: DeserializeOwned,
1271 {
1272 self.try_get_body_json().unwrap()
1273 }
1274
1275 /// Checks whether the WebSocket upgrade is enabled for this request.
1276 ///
1277 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1278 ///
1279 /// # Returns
1280 ///
1281 /// - `bool` - Whether WebSocket upgrade is enabled.
1282 #[inline(always)]
1283 pub fn is_ws_upgrade_type(&self) -> bool {
1284 self.get_upgrade_type().is_ws()
1285 }
1286
1287 /// Checks whether the request declares a `multipart/form-data` body.
1288 ///
1289 /// # Returns
1290 ///
1291 /// - `bool` - Whether the request content type is `multipart/form-data`.
1292 #[inline(always)]
1293 pub fn is_multipart_form_data(&self) -> bool {
1294 self.try_get_content_type()
1295 .map(|content_type: String| MultipartFormData::is_form_data(content_type))
1296 .unwrap_or(false)
1297 }
1298
1299 /// Tries to get the request content type with its parameters stripped.
1300 ///
1301 /// A `Content-Type` header such as `text/html; charset=utf-8` yields the
1302 /// media type alone, so a caller comparing against a media type does not
1303 /// have to know that parameters may follow it.
1304 ///
1305 /// # Returns
1306 ///
1307 /// - `Option<RequestContentType>` - The media type, or `None` when the header is absent.
1308 #[inline(always)]
1309 pub fn try_get_content_type(&self) -> Option<RequestContentType> {
1310 self.try_get_header_front(CONTENT_TYPE)
1311 .map(|value: String| {
1312 value
1313 .split(SEMICOLON)
1314 .next()
1315 .unwrap_or(EMPTY_STR)
1316 .trim()
1317 .to_ascii_lowercase()
1318 })
1319 }
1320
1321 /// Tries to get one parameter of the request `Content-Type` header.
1322 ///
1323 /// The name is matched case-insensitively and a quoted value is unquoted,
1324 /// so both `boundary=abc` and `boundary="abc"` yield `abc`.
1325 ///
1326 /// # Arguments
1327 ///
1328 /// - `K` - The parameter name, which requires the `AsRef<str>` bound.
1329 ///
1330 /// # Returns
1331 ///
1332 /// - `Option<RequestContentTypeParameter>` - The parameter value, or `None` when absent.
1333 pub fn try_get_content_type_parameter<K>(&self, name: K) -> Option<RequestContentTypeParameter>
1334 where
1335 K: AsRef<str>,
1336 {
1337 let content_type: String = self.try_get_header_front(CONTENT_TYPE)?;
1338 let name: &str = name.as_ref();
1339 for parameter in content_type.split(SEMICOLON).skip(1) {
1340 let (key, value) = parameter.trim().split_once(EQUAL)?;
1341 if !key.trim().eq_ignore_ascii_case(name) {
1342 continue;
1343 }
1344 let value: &str = value.trim();
1345 let value: &str = value
1346 .strip_prefix(MULTIPART_PARAMETER_QUOTE)
1347 .and_then(|value: &str| value.strip_suffix(MULTIPART_PARAMETER_QUOTE))
1348 .unwrap_or(value);
1349 if !value.is_empty() {
1350 return Some(value.to_string());
1351 }
1352 }
1353 None
1354 }
1355
1356 /// Tries to decode a `multipart/form-data` body into its parts.
1357 ///
1358 /// The boundary is read from the request `Content-Type` header rather than
1359 /// guessed, so a body whose content type declares no boundary, a truncated
1360 /// body, and a part without a name all yield `None`.
1361 ///
1362 /// # Returns
1363 ///
1364 /// - `Option<MultipartFormDataParts>` - The decoded parts, or `None` when unavailable.
1365 pub fn try_get_body_form_data(&self) -> Option<MultipartFormDataParts> {
1366 let boundary: MultipartFormDataBoundary =
1367 self.try_get_content_type_parameter(MULTIPART_BOUNDARY_PARAMETER)?;
1368 MultipartFormData::parse(self.get_body(), &boundary)
1369 }
1370
1371 /// Decodes an `application/x-www-form-urlencoded` body into its fields.
1372 ///
1373 /// # Returns
1374 ///
1375 /// - `BodyForm` - The decoded form fields.
1376 #[inline(always)]
1377 pub fn get_body_form(&self) -> BodyForm {
1378 MultipartFormData::parse_url_encoded(self.get_body())
1379 }
1380
1381 /// Tries to get a plain text field of a `multipart/form-data` body.
1382 ///
1383 /// A part that uploads a file is skipped, so a file field never silently
1384 /// decodes as text.
1385 ///
1386 /// # Arguments
1387 ///
1388 /// - `K` - The form field name, which requires the `AsRef<str>` bound.
1389 ///
1390 /// # Returns
1391 ///
1392 /// - `Option<BodyFormValue>` - The field value, or `None` when absent or a file.
1393 pub fn try_get_body_form_data_text<K>(&self, name: K) -> Option<BodyFormValue>
1394 where
1395 K: AsRef<str>,
1396 {
1397 let parts: MultipartFormDataParts = self.try_get_body_form_data()?;
1398 MultipartFormData::try_get_part_text(&parts, name)
1399 }
1400
1401 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1402 ///
1403 /// # Returns
1404 ///
1405 /// - `bool` - Whether the upgrade type is h2c.
1406 #[inline(always)]
1407 pub fn is_h2c_upgrade_type(&self) -> bool {
1408 self.get_upgrade_type().is_h2c()
1409 }
1410
1411 /// Checks if the current upgrade type is TLS (any version).
1412 ///
1413 /// # Returns
1414 ///
1415 /// - `bool` - Whether the upgrade type is TLS.
1416 #[inline(always)]
1417 pub fn is_tls_upgrade_type(&self) -> bool {
1418 self.get_upgrade_type().is_tls()
1419 }
1420
1421 /// Checks whether the upgrade type is unknown.
1422 ///
1423 /// # Returns
1424 ///
1425 /// - `bool` - Whether the upgrade type is unknown.
1426 #[inline(always)]
1427 pub fn is_unknown_upgrade_type(&self) -> bool {
1428 self.get_upgrade_type().is_unknown()
1429 }
1430
1431 /// Determines if a keep-alive connection should be enabled for this request.
1432 ///
1433 /// This function checks the `Connection` header and the HTTP version to determine
1434 /// if keep-alive should be enabled. The logic is as follows:
1435 ///
1436 /// 1. If the `Connection` header exists:
1437 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1438 /// - Returns `false` if the header value is "close" (case-insensitive).
1439 /// 2. If no `Connection` header is present:
1440 /// - Returns `true` if the HTTP version is 1.1 or higher.
1441 /// - Returns `false` otherwise.
1442 ///
1443 /// # Returns
1444 ///
1445 /// - `bool` - Whether keep-alive should be enabled.
1446 #[inline(always)]
1447 pub fn is_enable_keep_alive(&self) -> bool {
1448 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1449 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1450 return true;
1451 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1452 return self.is_ws_upgrade_type();
1453 }
1454 }
1455 self.get_version().is_http1_1_or_higher() || self.is_ws_upgrade_type()
1456 }
1457
1458 /// Determines if keep-alive should be disabled for this request.
1459 ///
1460 /// # Returns
1461 ///
1462 /// - `bool` - Whether keep-alive should be disabled.
1463 #[inline(always)]
1464 pub fn is_disable_keep_alive(&self) -> bool {
1465 !self.is_enable_keep_alive()
1466 }
1467}