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    pub fn new() -> Self {
27        Self::default()
28    }
29
30    /// Parses an HTTP request from a buffered TCP stream reader.
31    ///
32    /// Reads request line, headers and body from the stream and constructs a Request object.
33    ///
34    /// # Arguments
35    ///
36    /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
37    /// - `usize` - The buffer size for reading.
38    ///
39    /// # Returns
40    ///
41    /// - `Result<Request, RequestError>` - The parsed request or an error.
42    pub async fn http_from_reader(
43        reader: &mut BufReader<&mut TcpStream>,
44        buffer: usize,
45    ) -> RequestReaderHandleResult {
46        let mut request_line: String = String::with_capacity(buffer);
47        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
48        let parts: Vec<&str> = request_line.split_whitespace().collect();
49        let parts_len: usize = parts.len();
50        if parts_len < 3 {
51            return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
52        }
53        let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
54        let full_path: RequestPath = parts[1].to_string();
55        let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
56        let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
57        let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
58        let query_string: String = query_index.map_or(String::new(), |i| {
59            let temp: &str = &full_path[i + 1..];
60            if hash_index.is_none() || hash_index.unwrap() <= i {
61                return temp.to_string();
62            }
63            temp.split(HASH_SYMBOL)
64                .next()
65                .unwrap_or_default()
66                .to_string()
67        });
68        let querys: RequestQuerys = Self::parse_querys(&query_string);
69        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
70            full_path[..i].to_string()
71        } else {
72            full_path
73        };
74        let mut headers: RequestHeaders = hash_map_xx_hash3_64();
75        let mut host: RequestHost = String::new();
76        let mut content_length: usize = 0;
77        loop {
78            let mut header_line: String = String::with_capacity(buffer);
79            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
80            let header_line: &str = header_line.trim();
81            if header_line.is_empty() {
82                break;
83            }
84            if let Some((key_part, value_part)) = header_line.split_once(COLON_SPACE_SYMBOL) {
85                let key: String = key_part.trim().to_ascii_lowercase();
86                if key.is_empty() {
87                    continue;
88                }
89                let value: String = value_part.trim().to_string();
90                if key == HOST {
91                    host = value.clone();
92                } else if key == CONTENT_LENGTH {
93                    content_length = value.parse().unwrap_or(0);
94                }
95                headers
96                    .entry(key)
97                    .or_insert_with(VecDeque::new)
98                    .push_back(value);
99            }
100        }
101        let mut body: RequestBody = vec![0; content_length];
102        if content_length > 0 {
103            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
104        }
105        Ok(Request {
106            method,
107            host,
108            version,
109            path,
110            querys,
111            headers,
112            body,
113        })
114    }
115
116    /// Parses an HTTP request from a TCP stream.
117    ///
118    /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
119    ///
120    /// # Arguments
121    ///
122    /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
123    /// - `usize` - The buffer size for reading.
124    ///
125    /// # Returns
126    ///
127    /// - `Result<Request, RequestError>` - The parsed request or an error.
128    pub async fn http_from_stream(
129        stream: &ArcRwLockStream,
130        buffer: usize,
131    ) -> RequestReaderHandleResult {
132        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
133        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
134        Self::http_from_reader(&mut reader, buffer).await
135    }
136
137    /// Parses a WebSocket request from a TCP stream.
138    ///
139    /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
140    ///
141    /// # Arguments
142    ///
143    /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
144    /// - `usize` - The buffer size for reading.
145    /// - `&mut Request` - The request template to populate.
146    ///
147    /// # Returns
148    ///
149    /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
150    pub async fn ws_from_stream(
151        stream: &ArcRwLockStream,
152        buffer: usize,
153        request: &mut Self,
154    ) -> RequestReaderHandleResult {
155        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
156        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
157        Self::ws_from_reader(&mut reader, buffer, request).await
158    }
159
160    /// Parses a WebSocket request from a buffered TCP stream.
161    ///
162    /// Handles WebSocket frames including text, binary, ping, pong and close frames.
163    /// Assembles the request body from frame payload data.
164    ///
165    /// # Arguments
166    ///
167    /// - `&mut BufReader<&mut TcpStream>` - The buffered TCP stream reader.
168    /// - `usize` - The buffer size for reading frames.
169    /// - `&mut Request` - The request template to populate.
170    ///
171    /// # Returns
172    ///
173    /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
174    pub async fn ws_from_reader(
175        reader: &mut BufReader<&mut TcpStream>,
176        buffer: usize,
177        request: &mut Self,
178    ) -> RequestReaderHandleResult {
179        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer);
180        let mut temp_buffer: Vec<u8> = vec![0; buffer];
181        let mut full_frame: Vec<u8> = Vec::new();
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    pub fn try_get_query<K>(&self, key: K) -> OptionRequestQuerysValue
272    where
273        K: AsRef<str>,
274    {
275        self.querys.get(key.as_ref()).cloned()
276    }
277
278    /// Retrieves the value of a request header by its key.
279    ///
280    /// # Arguments
281    ///
282    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
283    ///
284    /// # Returns
285    ///
286    /// - `OptionRequestHeadersValue` - The optional header values.
287    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    pub fn try_get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
304    where
305        K: AsRef<str>,
306    {
307        self.headers
308            .get(key.as_ref())
309            .and_then(|values| values.front().cloned())
310    }
311
312    /// Retrieves the last value of a request header by its key.
313    ///
314    /// # Arguments
315    ///
316    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
317    ///
318    /// # Returns
319    ///
320    /// - `OptionRequestHeadersValueItem` - The last header value if exists.
321    pub fn try_get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
322    where
323        K: AsRef<str>,
324    {
325        self.headers
326            .get(key.as_ref())
327            .and_then(|values| values.back().cloned())
328    }
329
330    /// Retrieves the number of values for a specific header.
331    ///
332    /// # Arguments
333    ///
334    /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
335    ///
336    /// # Returns
337    ///
338    /// - `usize` - The count of values for the header.
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    pub fn get_headers_values_length(&self) -> usize {
355        self.headers.values().map(|values| values.len()).sum()
356    }
357
358    /// Retrieves the number of unique headers.
359    ///
360    /// # Returns
361    ///
362    /// - `usize` - The count of unique header keys.
363    pub fn get_headers_length(&self) -> usize {
364        self.headers.len()
365    }
366
367    /// Checks if a specific header exists.
368    ///
369    /// # Arguments
370    ///
371    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
372    ///
373    /// # Returns
374    ///
375    /// - `bool` - Whether the header exists.
376    pub fn has_header<K>(&self, key: K) -> bool
377    where
378        K: AsRef<str>,
379    {
380        self.headers.contains_key(key.as_ref())
381    }
382
383    /// Checks if a header contains a specific value.
384    ///
385    /// # Arguments
386    ///
387    /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
388    /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
389    ///
390    /// # Returns
391    ///
392    /// - `bool` - Whether the header contains the value.
393    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
394    where
395        K: AsRef<str>,
396        V: AsRef<str>,
397    {
398        if let Some(values) = self.headers.get(key.as_ref()) {
399            values.contains(&value.as_ref().to_owned())
400        } else {
401            false
402        }
403    }
404
405    /// Retrieves the body content of the request as a UTF-8 encoded string.
406    ///
407    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
408    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
409    ///
410    /// # Returns
411    ///
412    /// - `String` - The body content as a string.
413    pub fn get_body_string(&self) -> String {
414        String::from_utf8_lossy(self.get_body()).into_owned()
415    }
416
417    /// Deserializes the body content of the request as_ref a specified type `T`.
418    ///
419    /// This method first retrieves the body content as a byte slice using `self.get_body()`.
420    /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
421    ///
422    /// # Arguments
423    ///
424    /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
425    ///
426    /// # Returns
427    ///
428    /// - `ResultJsonError<T>` - The deserialization result.
429    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
430    where
431        T: DeserializeOwned,
432    {
433        json_from_slice(self.get_body())
434    }
435
436    /// Converts the request to a formatted string representation.
437    ///
438    /// This method provides a human-readable summary of the request, including its method,
439    /// host, version, path, query parameters, headers, and body information.
440    ///
441    /// # Returns
442    ///
443    /// - `String` - The formatted request details.
444    pub fn get_string(&self) -> String {
445        let body: &Vec<u8> = self.get_body();
446        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
447            PLAIN
448        } else {
449            BINARY
450        };
451        format!(
452            "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
453            self.get_method(),
454            self.get_host(),
455            self.get_version(),
456            self.get_path(),
457            self.get_querys(),
458            self.get_headers(),
459            body.len(),
460            body_type
461        )
462    }
463
464    /// Retrieves the upgrade type from the request headers.
465    ///
466    /// This method looks for the `UPGRADE` header and attempts to parse its value
467    /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
468    /// it returns the default `UpgradeType`.
469    ///
470    /// # Returns
471    ///
472    /// - `UpgradeType` - The parsed upgrade type.
473    pub fn get_upgrade_type(&self) -> UpgradeType {
474        let upgrade_type: UpgradeType = self
475            .try_get_header_back(UPGRADE)
476            .and_then(|data| data.parse::<UpgradeType>().ok())
477            .unwrap_or_default();
478        upgrade_type
479    }
480
481    /// Checks whether the WebSocket upgrade is enabled for this request.
482    ///
483    /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
484    ///
485    /// # Returns
486    ///
487    /// - `bool` - Whether WebSocket upgrade is enabled.
488    pub fn is_ws(&self) -> bool {
489        self.get_upgrade_type().is_ws()
490    }
491
492    /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
493    ///
494    /// # Returns
495    ///
496    /// - `bool` - Whether the upgrade type is h2c.
497    pub fn is_h2c(&self) -> bool {
498        self.get_upgrade_type().is_h2c()
499    }
500
501    /// Checks if the current upgrade type is TLS (any version).
502    ///
503    /// # Returns
504    ///
505    /// - `bool` - Whether the upgrade type is TLS.
506    pub fn is_tls(&self) -> bool {
507        self.get_upgrade_type().is_tls()
508    }
509
510    /// Checks whether the upgrade type is unknown.
511    ///
512    /// # Returns
513    ///
514    /// - `bool` - Whether the upgrade type is unknown.
515    pub fn is_unknown_upgrade(&self) -> bool {
516        self.get_upgrade_type().is_unknown()
517    }
518
519    /// Checks if the HTTP version is HTTP/1.1 or higher.
520    ///
521    /// # Returns
522    ///
523    /// - `bool` - Whether the version is HTTP/1.1 or higher.
524    pub fn is_http1_1_or_higher(&self) -> bool {
525        self.get_version().is_http1_1_or_higher()
526    }
527
528    /// Checks whether the HTTP version is HTTP/0.9.
529    ///
530    /// # Returns
531    ///
532    /// - `bool` - Whether the version is HTTP/0.9.
533    pub fn is_http0_9(&self) -> bool {
534        self.get_version().is_http0_9()
535    }
536
537    /// Checks whether the HTTP version is HTTP/1.0.
538    ///
539    /// # Returns
540    ///
541    /// - `bool` - Whether the version is HTTP/1.0.
542    pub fn is_http1_0(&self) -> bool {
543        self.get_version().is_http1_0()
544    }
545
546    /// Checks whether the HTTP version is HTTP/1.1.
547    ///
548    /// # Returns
549    ///
550    /// - `bool` - Whether the version is HTTP/1.1.
551    pub fn is_http1_1(&self) -> bool {
552        self.get_version().is_http1_1()
553    }
554
555    /// Checks whether the HTTP version is HTTP/2.
556    ///
557    /// # Returns
558    ///
559    /// - `bool` - Whether the version is HTTP/2.
560    pub fn is_http2(&self) -> bool {
561        self.get_version().is_http2()
562    }
563
564    /// Checks whether the HTTP version is HTTP/3.
565    ///
566    /// # Returns
567    ///
568    /// - `bool` - Whether the version is HTTP/3.
569    pub fn is_http3(&self) -> bool {
570        self.get_version().is_http3()
571    }
572
573    /// Checks whether the HTTP version is unknown.
574    ///
575    /// # Returns
576    ///
577    /// - `bool` - Whether the version is unknown.
578    pub fn is_unknown_version(&self) -> bool {
579        self.get_version().is_unknown()
580    }
581
582    /// Checks whether the version belongs to the HTTP family.
583    ///
584    /// # Returns
585    ///
586    /// - `bool` - Whether the version is HTTP.
587    pub fn is_http(&self) -> bool {
588        self.get_version().is_http()
589    }
590
591    /// Checks whether the request method is GET.
592    ///
593    /// # Returns
594    ///
595    /// - `bool` - Whether the method is GET.
596    pub fn is_get(&self) -> bool {
597        self.get_method().is_get()
598    }
599
600    /// Checks whether the request method is POST.
601    ///
602    /// # Returns
603    ///
604    /// - `bool` - Whether the method is POST.
605    pub fn is_post(&self) -> bool {
606        self.get_method().is_post()
607    }
608
609    /// Checks whether the request method is PUT.
610    ///
611    /// # Returns
612    ///
613    /// - `bool` - Whether the method is PUT.
614    pub fn is_put(&self) -> bool {
615        self.get_method().is_put()
616    }
617
618    /// Checks whether the request method is DELETE.
619    ///
620    /// # Returns
621    ///
622    /// - `bool` - Whether the method is DELETE.
623    pub fn is_delete(&self) -> bool {
624        self.get_method().is_delete()
625    }
626
627    /// Checks whether the request method is PATCH.
628    ///
629    /// # Returns
630    ///
631    /// - `bool` - Whether the method is PATCH.
632    pub fn is_patch(&self) -> bool {
633        self.get_method().is_patch()
634    }
635
636    /// Checks whether the request method is HEAD.
637    ///
638    /// # Returns
639    ///
640    /// - `bool` - Whether the method is HEAD.
641    pub fn is_head(&self) -> bool {
642        self.get_method().is_head()
643    }
644
645    /// Checks whether the request method is OPTIONS.
646    ///
647    /// # Returns
648    ///
649    /// - `bool` - Whether the method is OPTIONS.
650    pub fn is_options(&self) -> bool {
651        self.get_method().is_options()
652    }
653
654    /// Checks whether the request method is CONNECT.
655    ///
656    /// # Returns
657    ///
658    /// - `bool` - Whether the method is CONNECT.
659    pub fn is_connect(&self) -> bool {
660        self.get_method().is_connect()
661    }
662
663    /// Checks whether the request method is TRACE.
664    ///
665    /// # Returns
666    ///
667    /// - `bool` - Whether the method is TRACE.
668    pub fn is_trace(&self) -> bool {
669        self.get_method().is_trace()
670    }
671
672    /// Checks whether the request method is UNKNOWN.
673    ///
674    /// # Returns
675    ///
676    /// - `bool` - Whether the method is UNKNOWN.
677    pub fn is_unknown_method(&self) -> bool {
678        self.get_method().is_unknown()
679    }
680
681    /// Determines if a keep-alive connection should be enabled for this request.
682    ///
683    /// This function checks the `Connection` header and the HTTP version to determine
684    /// if keep-alive should be enabled. The logic is as follows:
685    ///
686    /// 1. If the `Connection` header exists:
687    ///    - Returns `true` if the header value is "keep-alive" (case-insensitive).
688    ///    - Returns `false` if the header value is "close" (case-insensitive).
689    /// 2. If no `Connection` header is present:
690    ///    - Returns `true` if the HTTP version is 1.1 or higher.
691    ///    - Returns `false` otherwise.
692    ///
693    /// # Returns
694    ///
695    /// - `bool` - Whether keep-alive should be enabled.
696    pub fn is_enable_keep_alive(&self) -> bool {
697        if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
698            if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
699                return true;
700            } else if connection_value.eq_ignore_ascii_case(CLOSE) {
701                return self.is_ws();
702            }
703        }
704        self.is_http1_1_or_higher() || self.is_ws()
705    }
706
707    /// Determines if keep-alive should be disabled for this request.
708    ///
709    /// # Returns
710    ///
711    /// - `bool` - Whether keep-alive should be disabled.
712    pub fn is_disable_keep_alive(&self) -> bool {
713        !self.is_enable_keep_alive()
714    }
715}