http_type/request/
impl.rs

1use crate::*;
2
3/// Provides a default value for `Request`.
4///
5/// Returns a new `Request` instance with all fields initialized to their default values.
6impl Default for Request {
7    fn default() -> Self {
8        Self {
9            method: Method::default(),
10            host: String::new(),
11            version: HttpVersion::default(),
12            path: String::new(),
13            querys: hash_map_xx_hash3_64(),
14            headers: hash_map_xx_hash3_64(),
15            body: Vec::new(),
16        }
17    }
18}
19
20impl Request {
21    /// Creates a new instance of `Request`.
22    ///
23    /// # Returns
24    ///
25    /// - `Request` - A new request instance with default values.
26    #[inline]
27    pub fn new() -> Self {
28        Self::default()
29    }
30
31    /// Parses an HTTP request from a buffered TCP stream reader.
32    ///
33    /// Reads request line, headers and body from the stream and constructs a Request object.
34    ///
35    /// # Arguments
36    ///
37    /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
38    /// - `usize` - The buffer size for reading.
39    ///
40    /// # Returns
41    ///
42    /// - `Result<Request, RequestError>` - The parsed request or an error.
43    pub async fn http_from_reader(
44        reader: &mut BufReader<&mut TcpStream>,
45        buffer: usize,
46    ) -> RequestReaderHandleResult {
47        let mut request_line: String = String::with_capacity(buffer.min(8192));
48        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
49        let parts: Vec<&str> = request_line.split_whitespace().collect();
50        let parts_len: usize = parts.len();
51        if parts_len < 3 {
52            return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
53        }
54        let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
55        let full_path: RequestPath = parts[1].to_string();
56        let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
57        let hash_index: OptionUsize = full_path.find(HASH);
58        let query_index: OptionUsize = full_path.find(QUERY);
59        let query_string: String = query_index.map_or_else(
60            || String::new(),
61            |i| {
62                let temp: &str = &full_path[i + 1..];
63                if hash_index.is_none() || hash_index.unwrap() <= i {
64                    return temp.to_owned();
65                }
66                temp.split(HASH).next().unwrap_or_default().to_owned()
67            },
68        );
69        let querys: RequestQuerys = Self::parse_querys(&query_string);
70        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
71            full_path[..i].to_owned()
72        } else {
73            full_path.to_owned()
74        };
75        let mut headers: RequestHeaders = hash_map_xx_hash3_64();
76        let mut host: RequestHost = String::new();
77        let mut content_length: usize = 0;
78        loop {
79            let mut header_line: String = String::with_capacity(buffer.min(DEFAULT_BUFFER_SIZE));
80            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
81            let header_line: &str = header_line.trim();
82            if header_line.is_empty() {
83                break;
84            }
85            if let Some((key_part, value_part)) = header_line.split_once(COLON) {
86                let key: String = key_part.trim().to_ascii_lowercase();
87                if key.is_empty() {
88                    continue;
89                }
90                let value: String = value_part.trim().to_string();
91                if key == HOST {
92                    host = value.clone();
93                } else if key == CONTENT_LENGTH {
94                    content_length = value.parse().unwrap_or(0);
95                }
96                headers.entry(key).or_default().push_back(value);
97            }
98        }
99        let mut body: RequestBody = vec![0; content_length];
100        if content_length > 0 {
101            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
102        }
103        Ok(Request {
104            method,
105            host,
106            version,
107            path,
108            querys,
109            headers,
110            body,
111        })
112    }
113
114    /// Parses an HTTP request from a TCP stream.
115    ///
116    /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
117    ///
118    /// # Arguments
119    ///
120    /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
121    /// - `usize` - The buffer size for reading.
122    ///
123    /// # Returns
124    ///
125    /// - `Result<Request, RequestError>` - The parsed request or an error.
126    pub async fn http_from_stream(
127        stream: &ArcRwLockStream,
128        buffer: usize,
129    ) -> RequestReaderHandleResult {
130        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
131        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
132        Self::http_from_reader(&mut reader, buffer).await
133    }
134
135    /// Parses a WebSocket request from a TCP stream.
136    ///
137    /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
138    ///
139    /// # Arguments
140    ///
141    /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
142    /// - `usize` - The buffer size for reading.
143    /// - `&mut Request` - The request template to populate.
144    ///
145    /// # Returns
146    ///
147    /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
148    pub async fn ws_from_stream(
149        stream: &ArcRwLockStream,
150        buffer: usize,
151        request: &mut Self,
152    ) -> RequestReaderHandleResult {
153        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
154        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
155        Self::ws_from_reader(&mut reader, buffer, request).await
156    }
157
158    /// Parses a WebSocket request from a buffered TCP stream.
159    ///
160    /// Handles WebSocket frames including text, binary, ping, pong and close frames.
161    /// Assembles the request body from frame payload data.
162    ///
163    /// # Arguments
164    ///
165    /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
166    /// - `usize` - The buffer size for reading frames.
167    /// - `&mut Request` - The request template to populate.
168    ///
169    /// # Returns
170    ///
171    /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
172    pub async fn ws_from_reader(
173        reader: &mut BufReader<&mut TcpStream>,
174        buffer: usize,
175        request: &mut Self,
176    ) -> RequestReaderHandleResult {
177        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer.min(DEFAULT_BUFFER_SIZE));
178        let temp_buffer_size: usize = buffer.min(DEFAULT_BUFFER_SIZE);
179        let mut temp_buffer: Vec<u8> = vec![0; temp_buffer_size];
180        let mut full_frame: Vec<u8> = Vec::with_capacity(buffer.min(DEFAULT_BUFFER_SIZE));
181        let mut error_handle = || {
182            request.body.clear();
183        };
184        loop {
185            let len: usize = match reader.read(&mut temp_buffer).await {
186                Ok(len) => len,
187                Err(err) => {
188                    error_handle();
189                    if err.kind() == ErrorKind::ConnectionReset
190                        || err.kind() == ErrorKind::ConnectionAborted
191                    {
192                        return Err(RequestError::ClientDisconnected);
193                    }
194                    return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
195                }
196            };
197            if len == 0 {
198                error_handle();
199                return Err(RequestError::IncompleteWebSocketFrame);
200            }
201            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
202            while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
203                dynamic_buffer.drain(0..consumed);
204                match frame.get_opcode() {
205                    WebSocketOpcode::Close => {
206                        error_handle();
207                        return Err(RequestError::ClientClosedConnection);
208                    }
209                    WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
210                        continue;
211                    }
212                    WebSocketOpcode::Text | WebSocketOpcode::Binary => {
213                        full_frame.extend_from_slice(frame.get_payload_data());
214                        if *frame.get_fin() {
215                            let mut request: Request = request.clone();
216                            request.body = full_frame;
217                            return Ok(request);
218                        }
219                    }
220                    _ => {
221                        error_handle();
222                        return Err(RequestError::InvalidWebSocketFrame(
223                            "Unsupported opcode".to_owned(),
224                        ));
225                    }
226                }
227            }
228        }
229    }
230
231    /// Parses a query string as_ref key-value pairs.
232    ///
233    /// Expects format "key1=value1&key2=value2". Empty values are allowed.
234    ///
235    /// # Arguments
236    ///
237    /// - `&str` - The query string to parse.
238    ///
239    /// # Returns
240    ///
241    /// - `HashMap<String, String>` - The parsed query parameters.
242    fn parse_querys<Q>(query: Q) -> RequestQuerys
243    where
244        Q: AsRef<str>,
245    {
246        let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
247        for pair in query.as_ref().split(AND) {
248            if let Some((key, value)) = pair.split_once(EQUAL) {
249                if !key.is_empty() {
250                    query_map.insert(key.to_string(), value.to_string());
251                }
252            } else if !pair.is_empty() {
253                query_map.insert(pair.to_string(), String::new());
254            }
255        }
256        query_map
257    }
258
259    /// Gets a query parameter value by key.
260    ///
261    /// The key type must implement AsRef<str> conversion.
262    ///
263    /// # Arguments
264    ///
265    /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
266    ///
267    /// # Returns
268    ///
269    /// - `Option<String>` - The parameter value if exists.
270    #[inline]
271    pub fn try_get_query<K>(&self, key: K) -> OptionRequestQuerysValue
272    where
273        K: AsRef<str>,
274    {
275        self.querys.get(key.as_ref()).cloned()
276    }
277
278    /// Retrieves the value of a request header by its key.
279    ///
280    /// # Arguments
281    ///
282    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
283    ///
284    /// # Returns
285    ///
286    /// - `OptionRequestHeadersValue` - The optional header values.
287    #[inline]
288    pub fn try_get_header<K>(&self, key: K) -> OptionRequestHeadersValue
289    where
290        K: AsRef<str>,
291    {
292        self.headers.get(key.as_ref()).cloned()
293    }
294
295    /// Retrieves the first value of a request header by its key.
296    ///
297    /// # Arguments
298    ///
299    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
300    ///
301    /// # Returns
302    ///
303    /// - `OptionRequestHeadersValueItem` - The first header value if exists.
304    #[inline]
305    pub fn try_get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
306    where
307        K: AsRef<str>,
308    {
309        self.headers
310            .get(key.as_ref())
311            .and_then(|values| values.front().cloned())
312    }
313
314    /// Retrieves the last value of a request header by its key.
315    ///
316    /// # Arguments
317    ///
318    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
319    ///
320    /// # Returns
321    ///
322    /// - `OptionRequestHeadersValueItem` - The last header value if exists.
323    #[inline]
324    pub fn try_get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
325    where
326        K: AsRef<str>,
327    {
328        self.headers
329            .get(key.as_ref())
330            .and_then(|values| values.back().cloned())
331    }
332
333    /// Retrieves the number of values for a specific header.
334    ///
335    /// # Arguments
336    ///
337    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
338    ///
339    /// # Returns
340    ///
341    /// - `usize` - The count of values for the header.
342    #[inline]
343    pub fn get_header_length<K>(&self, key: K) -> usize
344    where
345        K: AsRef<str>,
346    {
347        self.headers
348            .get(key.as_ref())
349            .map(|values| values.len())
350            .unwrap_or(0)
351    }
352
353    /// Retrieves the total number of header values across all headers.
354    ///
355    /// # Returns
356    ///
357    /// - `usize` - The total count of all header values.
358    #[inline]
359    pub fn get_headers_values_length(&self) -> usize {
360        self.headers.values().map(|values| values.len()).sum()
361    }
362
363    /// Retrieves the number of unique headers.
364    ///
365    /// # Returns
366    ///
367    /// - `usize` - The count of unique header keys.
368    #[inline]
369    pub fn get_headers_length(&self) -> usize {
370        self.headers.len()
371    }
372
373    /// Checks if a specific header exists.
374    ///
375    /// # Arguments
376    ///
377    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
378    ///
379    /// # Returns
380    ///
381    /// - `bool` - Whether the header exists.
382    #[inline]
383    pub fn has_header<K>(&self, key: K) -> bool
384    where
385        K: AsRef<str>,
386    {
387        self.headers.contains_key(key.as_ref())
388    }
389
390    /// Checks if a header contains a specific value.
391    ///
392    /// # Arguments
393    ///
394    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
395    /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
396    ///
397    /// # Returns
398    ///
399    /// - `bool` - Whether the header contains the value.
400    #[inline]
401    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
402    where
403        K: AsRef<str>,
404        V: AsRef<str>,
405    {
406        if let Some(values) = self.headers.get(key.as_ref()) {
407            values.contains(&value.as_ref().to_owned())
408        } else {
409            false
410        }
411    }
412
413    /// Retrieves the body content of the request as a UTF-8 encoded string.
414    ///
415    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
416    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
417    ///
418    /// # Returns
419    ///
420    /// - `String` - The body content as a string.
421    #[inline]
422    pub fn get_body_string(&self) -> String {
423        String::from_utf8_lossy(self.get_body()).into_owned()
424    }
425
426    /// Deserializes the body content of the request as_ref a specified type `T`.
427    ///
428    /// This method first retrieves the body content as a byte slice using `self.get_body()`.
429    /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
430    ///
431    /// # Arguments
432    ///
433    /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
434    ///
435    /// # Returns
436    ///
437    /// - `ResultJsonError<T>` - The deserialization result.
438    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
439    where
440        T: DeserializeOwned,
441    {
442        json_from_slice(self.get_body())
443    }
444
445    /// Converts the request to a formatted string representation.
446    ///
447    /// This method provides a human-readable summary of the request, including its method,
448    /// host, version, path, query parameters, headers, and body information.
449    ///
450    /// # Returns
451    ///
452    /// - `String` - The formatted request details.
453    #[inline]
454    pub fn get_string(&self) -> String {
455        let body: &Vec<u8> = self.get_body();
456        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
457            PLAIN
458        } else {
459            BINARY
460        };
461        format!(
462            "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
463            self.get_method(),
464            self.get_host(),
465            self.get_version(),
466            self.get_path(),
467            self.get_querys(),
468            self.get_headers(),
469            body.len(),
470            body_type
471        )
472    }
473
474    /// Retrieves the upgrade type from the request headers.
475    ///
476    /// This method looks for the `UPGRADE` header and attempts to parse its value
477    /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
478    /// it returns the default `UpgradeType`.
479    ///
480    /// # Returns
481    ///
482    /// - `UpgradeType` - The parsed upgrade type.
483    #[inline]
484    pub fn get_upgrade_type(&self) -> UpgradeType {
485        let upgrade_type: UpgradeType = self
486            .try_get_header_back(UPGRADE)
487            .and_then(|data| data.parse::<UpgradeType>().ok())
488            .unwrap_or_default();
489        upgrade_type
490    }
491
492    /// Checks whether the WebSocket upgrade is enabled for this request.
493    ///
494    /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
495    ///
496    /// # Returns
497    ///
498    /// - `bool` - Whether WebSocket upgrade is enabled.
499    #[inline]
500    pub fn is_ws(&self) -> bool {
501        self.get_upgrade_type().is_ws()
502    }
503
504    /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
505    ///
506    /// # Returns
507    ///
508    /// - `bool` - Whether the upgrade type is h2c.
509    #[inline]
510    pub fn is_h2c(&self) -> bool {
511        self.get_upgrade_type().is_h2c()
512    }
513
514    /// Checks if the current upgrade type is TLS (any version).
515    ///
516    /// # Returns
517    ///
518    /// - `bool` - Whether the upgrade type is TLS.
519    #[inline]
520    pub fn is_tls(&self) -> bool {
521        self.get_upgrade_type().is_tls()
522    }
523
524    /// Checks whether the upgrade type is unknown.
525    ///
526    /// # Returns
527    ///
528    /// - `bool` - Whether the upgrade type is unknown.
529    #[inline]
530    pub fn is_unknown_upgrade(&self) -> bool {
531        self.get_upgrade_type().is_unknown()
532    }
533
534    /// Checks if the HTTP version is HTTP/1.1 or higher.
535    ///
536    /// # Returns
537    ///
538    /// - `bool` - Whether the version is HTTP/1.1 or higher.
539    #[inline]
540    pub fn is_http1_1_or_higher(&self) -> bool {
541        self.get_version().is_http1_1_or_higher()
542    }
543
544    /// Checks whether the HTTP version is HTTP/0.9.
545    ///
546    /// # Returns
547    ///
548    /// - `bool` - Whether the version is HTTP/0.9.
549    #[inline]
550    pub fn is_http0_9(&self) -> bool {
551        self.get_version().is_http0_9()
552    }
553
554    /// Checks whether the HTTP version is HTTP/1.0.
555    ///
556    /// # Returns
557    ///
558    /// - `bool` - Whether the version is HTTP/1.0.
559    #[inline]
560    pub fn is_http1_0(&self) -> bool {
561        self.get_version().is_http1_0()
562    }
563
564    /// Checks whether the HTTP version is HTTP/1.1.
565    ///
566    /// # Returns
567    ///
568    /// - `bool` - Whether the version is HTTP/1.1.
569    #[inline]
570    pub fn is_http1_1(&self) -> bool {
571        self.get_version().is_http1_1()
572    }
573
574    /// Checks whether the HTTP version is HTTP/2.
575    ///
576    /// # Returns
577    ///
578    /// - `bool` - Whether the version is HTTP/2.
579    #[inline]
580    pub fn is_http2(&self) -> bool {
581        self.get_version().is_http2()
582    }
583
584    /// Checks whether the HTTP version is HTTP/3.
585    ///
586    /// # Returns
587    ///
588    /// - `bool` - Whether the version is HTTP/3.
589    #[inline]
590    pub fn is_http3(&self) -> bool {
591        self.get_version().is_http3()
592    }
593
594    /// Checks whether the HTTP version is unknown.
595    ///
596    /// # Returns
597    ///
598    /// - `bool` - Whether the version is unknown.
599    #[inline]
600    pub fn is_unknown_version(&self) -> bool {
601        self.get_version().is_unknown()
602    }
603
604    /// Checks whether the version belongs to the HTTP family.
605    ///
606    /// # Returns
607    ///
608    /// - `bool` - Whether the version is HTTP.
609    #[inline]
610    pub fn is_http(&self) -> bool {
611        self.get_version().is_http()
612    }
613
614    /// Checks whether the request method is GET.
615    ///
616    /// # Returns
617    ///
618    /// - `bool` - Whether the method is GET.
619    #[inline]
620    pub fn is_get(&self) -> bool {
621        self.get_method().is_get()
622    }
623
624    /// Checks whether the request method is POST.
625    ///
626    /// # Returns
627    ///
628    /// - `bool` - Whether the method is POST.
629    #[inline]
630    pub fn is_post(&self) -> bool {
631        self.get_method().is_post()
632    }
633
634    /// Checks whether the request method is PUT.
635    ///
636    /// # Returns
637    ///
638    /// - `bool` - Whether the method is PUT.
639    #[inline]
640    pub fn is_put(&self) -> bool {
641        self.get_method().is_put()
642    }
643
644    /// Checks whether the request method is DELETE.
645    ///
646    /// # Returns
647    ///
648    /// - `bool` - Whether the method is DELETE.
649    #[inline]
650    pub fn is_delete(&self) -> bool {
651        self.get_method().is_delete()
652    }
653
654    /// Checks whether the request method is PATCH.
655    ///
656    /// # Returns
657    ///
658    /// - `bool` - Whether the method is PATCH.
659    #[inline]
660    pub fn is_patch(&self) -> bool {
661        self.get_method().is_patch()
662    }
663
664    /// Checks whether the request method is HEAD.
665    ///
666    /// # Returns
667    ///
668    /// - `bool` - Whether the method is HEAD.
669    #[inline]
670    pub fn is_head(&self) -> bool {
671        self.get_method().is_head()
672    }
673
674    /// Checks whether the request method is OPTIONS.
675    ///
676    /// # Returns
677    ///
678    /// - `bool` - Whether the method is OPTIONS.
679    #[inline]
680    pub fn is_options(&self) -> bool {
681        self.get_method().is_options()
682    }
683
684    /// Checks whether the request method is CONNECT.
685    ///
686    /// # Returns
687    ///
688    /// - `bool` - Whether the method is CONNECT.
689    #[inline]
690    pub fn is_connect(&self) -> bool {
691        self.get_method().is_connect()
692    }
693
694    /// Checks whether the request method is TRACE.
695    ///
696    /// # Returns
697    ///
698    /// - `bool` - Whether the method is TRACE.
699    #[inline]
700    pub fn is_trace(&self) -> bool {
701        self.get_method().is_trace()
702    }
703
704    /// Checks whether the request method is UNKNOWN.
705    ///
706    /// # Returns
707    ///
708    /// - `bool` - Whether the method is UNKNOWN.
709    #[inline]
710    pub fn is_unknown_method(&self) -> bool {
711        self.get_method().is_unknown()
712    }
713
714    /// Determines if a keep-alive connection should be enabled for this request.
715    ///
716    /// This function checks the `Connection` header and the HTTP version to determine
717    /// if keep-alive should be enabled. The logic is as follows:
718    ///
719    /// 1. If the `Connection` header exists:
720    ///    - Returns `true` if the header value is "keep-alive" (case-insensitive).
721    ///    - Returns `false` if the header value is "close" (case-insensitive).
722    /// 2. If no `Connection` header is present:
723    ///    - Returns `true` if the HTTP version is 1.1 or higher.
724    ///    - Returns `false` otherwise.
725    ///
726    /// # Returns
727    ///
728    /// - `bool` - Whether keep-alive should be enabled.
729    #[inline]
730    pub fn is_enable_keep_alive(&self) -> bool {
731        if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
732            if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
733                return true;
734            } else if connection_value.eq_ignore_ascii_case(CLOSE) {
735                return self.is_ws();
736            }
737        }
738        self.is_http1_1_or_higher() || self.is_ws()
739    }
740
741    /// Determines if keep-alive should be disabled for this request.
742    ///
743    /// # Returns
744    ///
745    /// - `bool` - Whether keep-alive should be disabled.
746    #[inline]
747    pub fn is_disable_keep_alive(&self) -> bool {
748        !self.is_enable_keep_alive()
749    }
750}