Skip to main content

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}