http_type/request/
impl.rs

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