Skip to main content

http_type/request/
impl.rs

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