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