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