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