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);
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_SYMBOL);
58        let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
59        let query_string: String = query_index.map_or(String::new(), |i| {
60            let temp: &str = &full_path[i + 1..];
61            if hash_index.is_none() || hash_index.unwrap() <= i {
62                return temp.to_string();
63            }
64            temp.split(HASH_SYMBOL)
65                .next()
66                .unwrap_or_default()
67                .to_string()
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_string()
72        } else {
73            full_path
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);
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_SPACE_SYMBOL) {
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);
178        let mut temp_buffer: Vec<u8> = vec![0; buffer];
179        let mut full_frame: Vec<u8> = Vec::new();
180        let mut error_handle = || {
181            request.body.clear();
182        };
183        loop {
184            let len: usize = match reader.read(&mut temp_buffer).await {
185                Ok(len) => len,
186                Err(err) => {
187                    error_handle();
188                    if err.kind() == ErrorKind::ConnectionReset
189                        || err.kind() == ErrorKind::ConnectionAborted
190                    {
191                        return Err(RequestError::ClientDisconnected);
192                    }
193                    return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
194                }
195            };
196            if len == 0 {
197                error_handle();
198                return Err(RequestError::IncompleteWebSocketFrame);
199            }
200            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
201            while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
202                dynamic_buffer.drain(0..consumed);
203                match frame.get_opcode() {
204                    WebSocketOpcode::Close => {
205                        error_handle();
206                        return Err(RequestError::ClientClosedConnection);
207                    }
208                    WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
209                        continue;
210                    }
211                    WebSocketOpcode::Text | WebSocketOpcode::Binary => {
212                        full_frame.extend_from_slice(frame.get_payload_data());
213                        if *frame.get_fin() {
214                            let mut request: Request = request.clone();
215                            request.body = full_frame;
216                            return Ok(request);
217                        }
218                    }
219                    _ => {
220                        error_handle();
221                        return Err(RequestError::InvalidWebSocketFrame(
222                            "Unsupported opcode".to_owned(),
223                        ));
224                    }
225                }
226            }
227        }
228    }
229
230    /// Parses a query string as_ref key-value pairs.
231    ///
232    /// Expects format "key1=value1&key2=value2". Empty values are allowed.
233    ///
234    /// # Arguments
235    ///
236    /// - `&str` - The query string to parse.
237    ///
238    /// # Returns
239    ///
240    /// - `HashMap<String, String>` - The parsed query parameters.
241    fn parse_querys<Q>(query: Q) -> RequestQuerys
242    where
243        Q: AsRef<str>,
244    {
245        let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
246        for pair in query.as_ref().split(AND) {
247            if let Some((key, value)) = pair.split_once(EQUAL) {
248                if !key.is_empty() {
249                    query_map.insert(key.to_string(), value.to_string());
250                }
251            } else if !pair.is_empty() {
252                query_map.insert(pair.to_string(), String::new());
253            }
254        }
255        query_map
256    }
257
258    /// Gets a query parameter value by key.
259    ///
260    /// The key type must implement AsRef<str> conversion.
261    ///
262    /// # Arguments
263    ///
264    /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
265    ///
266    /// # Returns
267    ///
268    /// - `Option<String>` - The parameter value if exists.
269    #[inline]
270    pub fn try_get_query<K>(&self, key: K) -> OptionRequestQuerysValue
271    where
272        K: AsRef<str>,
273    {
274        self.querys.get(key.as_ref()).cloned()
275    }
276
277    /// Retrieves the value of a request header by its key.
278    ///
279    /// # Arguments
280    ///
281    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
282    ///
283    /// # Returns
284    ///
285    /// - `OptionRequestHeadersValue` - The optional header values.
286    #[inline]
287    pub fn try_get_header<K>(&self, key: K) -> OptionRequestHeadersValue
288    where
289        K: AsRef<str>,
290    {
291        self.headers.get(key.as_ref()).cloned()
292    }
293
294    /// Retrieves the first value of a request header by its key.
295    ///
296    /// # Arguments
297    ///
298    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
299    ///
300    /// # Returns
301    ///
302    /// - `OptionRequestHeadersValueItem` - The first header value if exists.
303    #[inline]
304    pub fn try_get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
305    where
306        K: AsRef<str>,
307    {
308        self.headers
309            .get(key.as_ref())
310            .and_then(|values| values.front().cloned())
311    }
312
313    /// Retrieves the last value of a request header by its key.
314    ///
315    /// # Arguments
316    ///
317    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
318    ///
319    /// # Returns
320    ///
321    /// - `OptionRequestHeadersValueItem` - The last header value if exists.
322    #[inline]
323    pub fn try_get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
324    where
325        K: AsRef<str>,
326    {
327        self.headers
328            .get(key.as_ref())
329            .and_then(|values| values.back().cloned())
330    }
331
332    /// Retrieves the number of values for a specific header.
333    ///
334    /// # Arguments
335    ///
336    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
337    ///
338    /// # Returns
339    ///
340    /// - `usize` - The count of values for the header.
341    #[inline]
342    pub fn get_header_length<K>(&self, key: K) -> usize
343    where
344        K: AsRef<str>,
345    {
346        self.headers
347            .get(key.as_ref())
348            .map(|values| values.len())
349            .unwrap_or(0)
350    }
351
352    /// Retrieves the total number of header values across all headers.
353    ///
354    /// # Returns
355    ///
356    /// - `usize` - The total count of all header values.
357    #[inline]
358    pub fn get_headers_values_length(&self) -> usize {
359        self.headers.values().map(|values| values.len()).sum()
360    }
361
362    /// Retrieves the number of unique headers.
363    ///
364    /// # Returns
365    ///
366    /// - `usize` - The count of unique header keys.
367    #[inline]
368    pub fn get_headers_length(&self) -> usize {
369        self.headers.len()
370    }
371
372    /// Checks if a specific header exists.
373    ///
374    /// # Arguments
375    ///
376    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
377    ///
378    /// # Returns
379    ///
380    /// - `bool` - Whether the header exists.
381    #[inline]
382    pub fn has_header<K>(&self, key: K) -> bool
383    where
384        K: AsRef<str>,
385    {
386        self.headers.contains_key(key.as_ref())
387    }
388
389    /// Checks if a header contains a specific value.
390    ///
391    /// # Arguments
392    ///
393    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
394    /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
395    ///
396    /// # Returns
397    ///
398    /// - `bool` - Whether the header contains the value.
399    #[inline]
400    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
401    where
402        K: AsRef<str>,
403        V: AsRef<str>,
404    {
405        if let Some(values) = self.headers.get(key.as_ref()) {
406            values.contains(&value.as_ref().to_owned())
407        } else {
408            false
409        }
410    }
411
412    /// Retrieves the body content of the request as a UTF-8 encoded string.
413    ///
414    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
415    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
416    ///
417    /// # Returns
418    ///
419    /// - `String` - The body content as a string.
420    #[inline]
421    pub fn get_body_string(&self) -> String {
422        String::from_utf8_lossy(self.get_body()).into_owned()
423    }
424
425    /// Deserializes the body content of the request as_ref a specified type `T`.
426    ///
427    /// This method first retrieves the body content as a byte slice using `self.get_body()`.
428    /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
429    ///
430    /// # Arguments
431    ///
432    /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
433    ///
434    /// # Returns
435    ///
436    /// - `ResultJsonError<T>` - The deserialization result.
437    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
438    where
439        T: DeserializeOwned,
440    {
441        json_from_slice(self.get_body())
442    }
443
444    /// Converts the request to a formatted string representation.
445    ///
446    /// This method provides a human-readable summary of the request, including its method,
447    /// host, version, path, query parameters, headers, and body information.
448    ///
449    /// # Returns
450    ///
451    /// - `String` - The formatted request details.
452    #[inline]
453    pub fn get_string(&self) -> String {
454        let body: &Vec<u8> = self.get_body();
455        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
456            PLAIN
457        } else {
458            BINARY
459        };
460        format!(
461            "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
462            self.get_method(),
463            self.get_host(),
464            self.get_version(),
465            self.get_path(),
466            self.get_querys(),
467            self.get_headers(),
468            body.len(),
469            body_type
470        )
471    }
472
473    /// Retrieves the upgrade type from the request headers.
474    ///
475    /// This method looks for the `UPGRADE` header and attempts to parse its value
476    /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
477    /// it returns the default `UpgradeType`.
478    ///
479    /// # Returns
480    ///
481    /// - `UpgradeType` - The parsed upgrade type.
482    #[inline]
483    pub fn get_upgrade_type(&self) -> UpgradeType {
484        let upgrade_type: UpgradeType = self
485            .try_get_header_back(UPGRADE)
486            .and_then(|data| data.parse::<UpgradeType>().ok())
487            .unwrap_or_default();
488        upgrade_type
489    }
490
491    /// Checks whether the WebSocket upgrade is enabled for this request.
492    ///
493    /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
494    ///
495    /// # Returns
496    ///
497    /// - `bool` - Whether WebSocket upgrade is enabled.
498    #[inline]
499    pub fn is_ws(&self) -> bool {
500        self.get_upgrade_type().is_ws()
501    }
502
503    /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
504    ///
505    /// # Returns
506    ///
507    /// - `bool` - Whether the upgrade type is h2c.
508    #[inline]
509    pub fn is_h2c(&self) -> bool {
510        self.get_upgrade_type().is_h2c()
511    }
512
513    /// Checks if the current upgrade type is TLS (any version).
514    ///
515    /// # Returns
516    ///
517    /// - `bool` - Whether the upgrade type is TLS.
518    #[inline]
519    pub fn is_tls(&self) -> bool {
520        self.get_upgrade_type().is_tls()
521    }
522
523    /// Checks whether the upgrade type is unknown.
524    ///
525    /// # Returns
526    ///
527    /// - `bool` - Whether the upgrade type is unknown.
528    #[inline]
529    pub fn is_unknown_upgrade(&self) -> bool {
530        self.get_upgrade_type().is_unknown()
531    }
532
533    /// Checks if the HTTP version is HTTP/1.1 or higher.
534    ///
535    /// # Returns
536    ///
537    /// - `bool` - Whether the version is HTTP/1.1 or higher.
538    #[inline]
539    pub fn is_http1_1_or_higher(&self) -> bool {
540        self.get_version().is_http1_1_or_higher()
541    }
542
543    /// Checks whether the HTTP version is HTTP/0.9.
544    ///
545    /// # Returns
546    ///
547    /// - `bool` - Whether the version is HTTP/0.9.
548    #[inline]
549    pub fn is_http0_9(&self) -> bool {
550        self.get_version().is_http0_9()
551    }
552
553    /// Checks whether the HTTP version is HTTP/1.0.
554    ///
555    /// # Returns
556    ///
557    /// - `bool` - Whether the version is HTTP/1.0.
558    #[inline]
559    pub fn is_http1_0(&self) -> bool {
560        self.get_version().is_http1_0()
561    }
562
563    /// Checks whether the HTTP version is HTTP/1.1.
564    ///
565    /// # Returns
566    ///
567    /// - `bool` - Whether the version is HTTP/1.1.
568    #[inline]
569    pub fn is_http1_1(&self) -> bool {
570        self.get_version().is_http1_1()
571    }
572
573    /// Checks whether the HTTP version is HTTP/2.
574    ///
575    /// # Returns
576    ///
577    /// - `bool` - Whether the version is HTTP/2.
578    #[inline]
579    pub fn is_http2(&self) -> bool {
580        self.get_version().is_http2()
581    }
582
583    /// Checks whether the HTTP version is HTTP/3.
584    ///
585    /// # Returns
586    ///
587    /// - `bool` - Whether the version is HTTP/3.
588    #[inline]
589    pub fn is_http3(&self) -> bool {
590        self.get_version().is_http3()
591    }
592
593    /// Checks whether the HTTP version is unknown.
594    ///
595    /// # Returns
596    ///
597    /// - `bool` - Whether the version is unknown.
598    #[inline]
599    pub fn is_unknown_version(&self) -> bool {
600        self.get_version().is_unknown()
601    }
602
603    /// Checks whether the version belongs to the HTTP family.
604    ///
605    /// # Returns
606    ///
607    /// - `bool` - Whether the version is HTTP.
608    #[inline]
609    pub fn is_http(&self) -> bool {
610        self.get_version().is_http()
611    }
612
613    /// Checks whether the request method is GET.
614    ///
615    /// # Returns
616    ///
617    /// - `bool` - Whether the method is GET.
618    #[inline]
619    pub fn is_get(&self) -> bool {
620        self.get_method().is_get()
621    }
622
623    /// Checks whether the request method is POST.
624    ///
625    /// # Returns
626    ///
627    /// - `bool` - Whether the method is POST.
628    #[inline]
629    pub fn is_post(&self) -> bool {
630        self.get_method().is_post()
631    }
632
633    /// Checks whether the request method is PUT.
634    ///
635    /// # Returns
636    ///
637    /// - `bool` - Whether the method is PUT.
638    #[inline]
639    pub fn is_put(&self) -> bool {
640        self.get_method().is_put()
641    }
642
643    /// Checks whether the request method is DELETE.
644    ///
645    /// # Returns
646    ///
647    /// - `bool` - Whether the method is DELETE.
648    #[inline]
649    pub fn is_delete(&self) -> bool {
650        self.get_method().is_delete()
651    }
652
653    /// Checks whether the request method is PATCH.
654    ///
655    /// # Returns
656    ///
657    /// - `bool` - Whether the method is PATCH.
658    #[inline]
659    pub fn is_patch(&self) -> bool {
660        self.get_method().is_patch()
661    }
662
663    /// Checks whether the request method is HEAD.
664    ///
665    /// # Returns
666    ///
667    /// - `bool` - Whether the method is HEAD.
668    #[inline]
669    pub fn is_head(&self) -> bool {
670        self.get_method().is_head()
671    }
672
673    /// Checks whether the request method is OPTIONS.
674    ///
675    /// # Returns
676    ///
677    /// - `bool` - Whether the method is OPTIONS.
678    #[inline]
679    pub fn is_options(&self) -> bool {
680        self.get_method().is_options()
681    }
682
683    /// Checks whether the request method is CONNECT.
684    ///
685    /// # Returns
686    ///
687    /// - `bool` - Whether the method is CONNECT.
688    #[inline]
689    pub fn is_connect(&self) -> bool {
690        self.get_method().is_connect()
691    }
692
693    /// Checks whether the request method is TRACE.
694    ///
695    /// # Returns
696    ///
697    /// - `bool` - Whether the method is TRACE.
698    #[inline]
699    pub fn is_trace(&self) -> bool {
700        self.get_method().is_trace()
701    }
702
703    /// Checks whether the request method is UNKNOWN.
704    ///
705    /// # Returns
706    ///
707    /// - `bool` - Whether the method is UNKNOWN.
708    #[inline]
709    pub fn is_unknown_method(&self) -> bool {
710        self.get_method().is_unknown()
711    }
712
713    /// Determines if a keep-alive connection should be enabled for this request.
714    ///
715    /// This function checks the `Connection` header and the HTTP version to determine
716    /// if keep-alive should be enabled. The logic is as follows:
717    ///
718    /// 1. If the `Connection` header exists:
719    ///    - Returns `true` if the header value is "keep-alive" (case-insensitive).
720    ///    - Returns `false` if the header value is "close" (case-insensitive).
721    /// 2. If no `Connection` header is present:
722    ///    - Returns `true` if the HTTP version is 1.1 or higher.
723    ///    - Returns `false` otherwise.
724    ///
725    /// # Returns
726    ///
727    /// - `bool` - Whether keep-alive should be enabled.
728    #[inline]
729    pub fn is_enable_keep_alive(&self) -> bool {
730        if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
731            if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
732                return true;
733            } else if connection_value.eq_ignore_ascii_case(CLOSE) {
734                return self.is_ws();
735            }
736        }
737        self.is_http1_1_or_higher() || self.is_ws()
738    }
739
740    /// Determines if keep-alive should be disabled for this request.
741    ///
742    /// # Returns
743    ///
744    /// - `bool` - Whether keep-alive should be disabled.
745    #[inline]
746    pub fn is_disable_keep_alive(&self) -> bool {
747        !self.is_enable_keep_alive()
748    }
749}