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