http_type/request/
impl.rs

1use crate::*;
2
3impl Default for Request {
4    fn default() -> Self {
5        Self {
6            method: Method::default(),
7            host: String::new(),
8            version: HttpVersion::default(),
9            path: String::new(),
10            querys: hash_map_xx_hash3_64(),
11            headers: hash_map_xx_hash3_64(),
12            body: Vec::new(),
13        }
14    }
15}
16
17impl Request {
18    /// Creates a new instance of `Request`.
19    ///
20    /// # Returns
21    /// - An initialized `Request` with default values.
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Creates a new `Request` object from a TCP stream.
27    ///
28    /// # Parameters
29    /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`.
30    /// - `buffer_size`: Request buffer size.
31    ///
32    /// # Returns
33    /// - `Ok`: A `Request` object populated with the HTTP request data.
34    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
35    pub async fn http_from_reader(
36        reader: &mut BufReader<&mut TcpStream>,
37        buffer_size: usize,
38    ) -> RequestReaderHandleResult {
39        let mut request_line: String = String::with_capacity(buffer_size);
40        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
41        let parts: Vec<&str> = request_line.split_whitespace().collect();
42        let parts_len: usize = parts.len();
43        if parts_len < 3 {
44            return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
45        }
46        let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
47        let full_path: RequestPath = parts[1].to_string();
48        let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
49        let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
50        let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
51        let query_string: String = query_index.map_or(String::new(), |i| {
52            let temp: &str = &full_path[i + 1..];
53            if hash_index.is_none() || hash_index.unwrap() <= i {
54                return temp.to_string();
55            }
56            temp.split(HASH_SYMBOL)
57                .next()
58                .unwrap_or_default()
59                .to_string()
60        });
61        let querys: RequestQuerys = Self::parse_querys(&query_string);
62        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
63            full_path[..i].to_string()
64        } else {
65            full_path
66        };
67        let mut headers: RequestHeaders = hash_map_xx_hash3_64();
68        let mut host: RequestHost = String::new();
69        let mut content_length: usize = 0;
70        loop {
71            let mut header_line: String = String::with_capacity(buffer_size);
72            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
73            let header_line: &str = header_line.trim();
74            if header_line.is_empty() {
75                break;
76            }
77            if let Some((key_part, value_part)) = header_line.split_once(COLON_SPACE_SYMBOL) {
78                let key: String = key_part.trim().to_ascii_lowercase();
79                if key.is_empty() {
80                    continue;
81                }
82                let value: String = value_part.trim().to_string();
83                if key == HOST {
84                    host = value.clone();
85                } else if key == CONTENT_LENGTH {
86                    content_length = value.parse().unwrap_or(0);
87                }
88                headers
89                    .entry(key)
90                    .or_insert_with(VecDeque::new)
91                    .push_back(value);
92            }
93        }
94        let mut body: RequestBody = vec![0; content_length];
95        if content_length > 0 {
96            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
97        }
98        Ok(Request {
99            method,
100            host,
101            version,
102            path,
103            querys,
104            headers,
105            body,
106        })
107    }
108
109    /// Creates a new `Request` object from a TCP stream.
110    ///
111    /// # Parameters
112    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
113    /// - `buffer_size`: Request buffer size.
114    ///
115    /// # Returns
116    /// - `Ok`: A `Request` object populated with the HTTP request data.
117    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
118    pub async fn http_from_stream(
119        stream: &ArcRwLockStream,
120        buffer_size: usize,
121    ) -> RequestReaderHandleResult {
122        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
123        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
124        Self::http_from_reader(&mut reader, buffer_size).await
125    }
126
127    /// Creates a new `Request` object from a TCP stream.
128    ///
129    /// # Parameters
130    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
131    /// - `buffer_size`: Request buffer size.
132    /// - `request`: A reference to a `Request` object. This object is used as a template.
133    ///
134    /// # Returns
135    /// - `Ok`: A `Request` object populated with the HTTP request data.
136    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
137    pub async fn ws_from_stream(
138        stream: &ArcRwLockStream,
139        buffer_size: usize,
140        request: &mut Self,
141    ) -> RequestReaderHandleResult {
142        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
143        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
144        Self::ws_from_reader(&mut reader, buffer_size, request).await
145    }
146
147    /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
148    ///
149    /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
150    /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
151    /// based on the received data. The request body is set using the received bytes.
152    ///
153    /// # Arguments
154    /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
155    ///   This reader is used to read the incoming WebSocket request data.
156    /// - `buffer_size`: - Request buffer size.
157    /// - `request` - A reference to a `Request` object. This object is used as a template.
158    ///
159    /// # Returns
160    /// - `Ok(Request)` - A `Request` object constructed from the received data.
161    ///   - If no data is read (`Ok(0)`), an empty `Request` object is returned.
162    ///   - If data is successfully read, the request body is set with the received bytes.
163    /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
164    pub async fn ws_from_reader(
165        reader: &mut BufReader<&mut TcpStream>,
166        buffer_size: usize,
167        request: &mut Self,
168    ) -> RequestReaderHandleResult {
169        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
170        let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
171        let mut full_frame: Vec<u8> = Vec::new();
172        let mut error_handle = || {
173            request.body.clear();
174        };
175        loop {
176            let len: usize = match reader.read(&mut temp_buffer).await {
177                Ok(len) => len,
178                Err(err) => {
179                    error_handle();
180                    if err.kind() == ErrorKind::ConnectionReset
181                        || err.kind() == ErrorKind::ConnectionAborted
182                    {
183                        return Err(RequestError::ClientDisconnected);
184                    }
185                    return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
186                }
187            };
188            if len == 0 {
189                error_handle();
190                return Err(RequestError::IncompleteWebSocketFrame);
191            }
192            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
193            while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
194                dynamic_buffer.drain(0..consumed);
195                match frame.get_opcode() {
196                    WebSocketOpcode::Close => {
197                        error_handle();
198                        return Err(RequestError::ClientClosedConnection);
199                    }
200                    WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
201                        continue;
202                    }
203                    WebSocketOpcode::Text | WebSocketOpcode::Binary => {
204                        full_frame.extend_from_slice(frame.get_payload_data());
205                        if *frame.get_fin() {
206                            let mut request: Request = request.clone();
207                            request.body = full_frame;
208                            return Ok(request);
209                        }
210                    }
211                    _ => {
212                        error_handle();
213                        return Err(RequestError::InvalidWebSocketFrame(
214                            "Unsupported opcode".into(),
215                        ));
216                    }
217                }
218            }
219        }
220    }
221
222    /// Parse querys
223    ///
224    /// # Parameters
225    /// - `query`: &str
226    ///
227    /// # Returns
228    /// - RequestQuerys
229    fn parse_querys(query: &str) -> RequestQuerys {
230        let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
231        for pair in query.split(AND) {
232            if let Some((key, value)) = pair.split_once(EQUAL) {
233                if !key.is_empty() {
234                    query_map.insert(key.to_string(), value.to_string());
235                }
236            } else if !pair.is_empty() {
237                query_map.insert(pair.to_string(), String::new());
238            }
239        }
240        query_map
241    }
242
243    /// Retrieves the value of a query parameter by its key.
244    ///
245    /// # Parameters
246    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
247    ///
248    /// # Returns
249    /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
250    ///   or `None` if the key does not exist.
251    pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
252    where
253        K: Into<RequestQuerysKey>,
254    {
255        self.querys.get(&key.into()).cloned()
256    }
257
258    /// Retrieves the value of a request header by its key.
259    ///
260    /// # Parameters
261    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
262    ///
263    /// # Returns
264    /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
265    ///   or `None` if the key does not exist.
266    pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
267    where
268        K: Into<RequestHeadersKey>,
269    {
270        self.headers.get(&key.into()).cloned()
271    }
272
273    /// Retrieves the first value of a request header by its key.
274    ///
275    /// # Parameters
276    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
277    ///
278    /// # Returns
279    /// - `OptionRequestHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
280    ///   or `None` if the key does not exist or has no values.
281    pub fn get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
282    where
283        K: Into<RequestHeadersKey>,
284    {
285        self.headers
286            .get(&key.into())
287            .and_then(|values| values.front().cloned())
288    }
289
290    /// Retrieves the last value of a request header by its key.
291    ///
292    /// # Parameters
293    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
294    ///
295    /// # Returns
296    /// - `OptionRequestHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
297    ///   or `None` if the key does not exist or has no values.
298    pub fn get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
299    where
300        K: Into<RequestHeadersKey>,
301    {
302        self.headers
303            .get(&key.into())
304            .and_then(|values| values.back().cloned())
305    }
306
307    /// Retrieves the number of values for a specific header.
308    ///
309    /// # Parameters
310    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
311    ///
312    /// # Returns
313    /// - `usize`: The number of values for the specified header. Returns 0 if the header does not exist.
314    pub fn get_header_len<K>(&self, key: K) -> usize
315    where
316        K: Into<RequestHeadersKey>,
317    {
318        self.headers
319            .get(&key.into())
320            .map(|values| values.len())
321            .unwrap_or(0)
322    }
323
324    /// Retrieves the total number of header values across all headers.
325    ///
326    /// # Returns
327    /// - `usize`: The total count of all header values.
328    pub fn get_headers_values_length(&self) -> usize {
329        self.headers.values().map(|values| values.len()).sum()
330    }
331
332    /// Retrieves the number of unique headers.
333    ///
334    /// # Returns
335    /// - `usize`: The number of unique header keys.
336    pub fn get_headers_length(&self) -> usize {
337        self.headers.len()
338    }
339
340    /// Checks if a specific header exists.
341    ///
342    /// # Parameters
343    /// - `key`: The header key to check, which will be converted into a `RequestHeadersKey`.
344    ///
345    /// # Returns
346    /// - `bool`: Returns `true` if the header exists, `false` otherwise.
347    pub fn has_header<K>(&self, key: K) -> bool
348    where
349        K: Into<RequestHeadersKey>,
350    {
351        self.headers.contains_key(&key.into())
352    }
353
354    /// Checks if a header contains a specific value.
355    ///
356    /// # Parameters
357    /// - `key`: The header key to check, which will be converted into a `RequestHeadersKey`.
358    /// - `value`: The value to search for in the header.
359    ///
360    /// # Returns
361    /// - `bool`: Returns `true` if the header exists and contains the specified value, `false` otherwise.
362    pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
363    where
364        K: Into<RequestHeadersKey>,
365        V: Into<RequestHeadersValueItem>,
366    {
367        let key: RequestHeadersKey = key.into();
368        let value: RequestHeadersValueItem = value.into();
369        if let Some(values) = self.headers.get(&key) {
370            values.contains(&value)
371        } else {
372            false
373        }
374    }
375
376    /// Retrieves the body content of the object as a UTF-8 encoded string.
377    ///
378    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
379    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
380    ///
381    /// # Returns
382    /// A `String` containing the body content.
383    pub fn get_body_string(&self) -> String {
384        String::from_utf8_lossy(self.get_body()).into_owned()
385    }
386
387    /// Deserializes the body content of the object into a specified type `T`.
388    ///
389    /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
390    /// It then attempts to deserialize the string into the specified type `T` using `json_from_slice`.
391    ///
392    /// # Type Parameters
393    /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
394    ///
395    /// # Returns
396    /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
397    /// - `Err(ResultJsonError)`: An error if the deserialization fails.
398    pub fn get_body_json<T>(&self) -> ResultJsonError<T>
399    where
400        T: DeserializeOwned,
401    {
402        json_from_slice(self.get_body())
403    }
404
405    /// Converts the request to a formatted string representation.
406    ///
407    /// - Returns: A `String` containing formatted request details.
408    pub fn get_string(&self) -> String {
409        let body: &Vec<u8> = self.get_body();
410        let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
411            PLAIN
412        } else {
413            BINARY
414        };
415        format!(
416            "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
417            self.get_method(),
418            self.get_host(),
419            self.get_version(),
420            self.get_path(),
421            self.get_querys(),
422            self.get_headers(),
423            body.len(),
424            body_type
425        )
426    }
427
428    /// Retrieves the upgrade type from the request headers.
429    ///
430    /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
431    ///            If the header is missing or invalid, returns the default `UpgradeType`.
432    pub fn get_upgrade_type(&self) -> UpgradeType {
433        let upgrade_type: UpgradeType = self
434            .get_header_back(UPGRADE)
435            .and_then(|data| data.parse::<UpgradeType>().ok())
436            .unwrap_or_default();
437        upgrade_type
438    }
439
440    /// Checks whether the WebSocket upgrade is enabled.
441    ///
442    /// - Returns: `true` if the upgrade type is WebSocket; otherwise, `false`.
443    pub fn is_ws(&self) -> bool {
444        self.get_upgrade_type().is_ws()
445    }
446
447    /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
448    ///
449    /// - `&self` - The current instance (usually a request or context struct).
450    ///
451    /// - Returns `true` if the upgrade type is `h2c`, otherwise `false`.
452    pub fn is_h2c(&self) -> bool {
453        self.get_upgrade_type().is_h2c()
454    }
455
456    /// Checks if the current upgrade type is TLS (any version).
457    ///
458    /// - `&self` - The current instance (usually a request or context struct).
459    ///
460    /// - Returns `true` if the upgrade type is any `Tls` variant, otherwise `false`.
461    pub fn is_tls(&self) -> bool {
462        self.get_upgrade_type().is_tls()
463    }
464
465    /// Checks whether the upgrade type is unknown.
466    ///
467    /// - Returns: `true` if the upgrade type is unknown; otherwise, `false`.
468    pub fn is_unknown_upgrade(&self) -> bool {
469        self.get_upgrade_type().is_unknown()
470    }
471
472    /// Checks if the HTTP version is HTTP/1.1 or higher.
473    ///
474    /// - Returns: `true` if the HTTP version is 1.1 or higher; otherwise, `false`.
475    pub fn is_http1_1_or_higher(&self) -> bool {
476        self.get_version().is_http1_1_or_higher()
477    }
478
479    /// Checks whether the HTTP version is HTTP/0.9.
480    ///
481    /// - Returns: `true` if the version is HTTP/0.9; otherwise, `false`.
482    pub fn is_http0_9(&self) -> bool {
483        self.get_version().is_http0_9()
484    }
485
486    /// Checks whether the HTTP version is HTTP/1.0.
487    ///
488    /// - Returns: `true` if the version is HTTP/1.0; otherwise, `false`.
489    pub fn is_http1_0(&self) -> bool {
490        self.get_version().is_http1_0()
491    }
492
493    /// Checks whether the HTTP version is HTTP/1.1.
494    ///
495    /// - Returns: `true` if the version is HTTP/1.1; otherwise, `false`.
496    pub fn is_http1_1(&self) -> bool {
497        self.get_version().is_http1_1()
498    }
499
500    /// Checks whether the HTTP version is HTTP/2.
501    ///
502    /// - Returns: `true` if the version is HTTP/2; otherwise, `false`.
503    pub fn is_http2(&self) -> bool {
504        self.get_version().is_http2()
505    }
506
507    /// Checks whether the HTTP version is HTTP/3.
508    ///
509    /// - Returns: `true` if the version is HTTP/3; otherwise, `false`.
510    pub fn is_http3(&self) -> bool {
511        self.get_version().is_http3()
512    }
513
514    /// Checks whether the HTTP version is unknown.
515    ///
516    /// - Returns: `true` if the version is unknown; otherwise, `false`.
517    pub fn is_unknown_version(&self) -> bool {
518        self.get_version().is_unknown()
519    }
520
521    /// Checks whether the version belongs to the HTTP family.
522    ///
523    /// - Returns: `true` if the version is a valid HTTP version; otherwise, `false`.
524    pub fn is_http(&self) -> bool {
525        self.get_version().is_http()
526    }
527
528    /// Checks whether the request method is `GET`.
529    ///
530    /// - Returns: `true` if the method is `GET`; otherwise, `false`.
531    pub fn is_get(&self) -> bool {
532        self.get_method().is_get()
533    }
534
535    /// Checks whether the request method is `POST`.
536    ///
537    /// - Returns: `true` if the method is `POST`; otherwise, `false`.
538    pub fn is_post(&self) -> bool {
539        self.get_method().is_post()
540    }
541
542    /// Checks whether the request method is `PUT`.
543    ///
544    /// - Returns: `true` if the method is `PUT`; otherwise, `false`.
545    pub fn is_put(&self) -> bool {
546        self.get_method().is_put()
547    }
548
549    /// Checks whether the request method is `DELETE`.
550    ///
551    /// - Returns: `true` if the method is `DELETE`; otherwise, `false`.
552    pub fn is_delete(&self) -> bool {
553        self.get_method().is_delete()
554    }
555
556    /// Checks whether the request method is `PATCH`.
557    ///
558    /// - Returns: `true` if the method is `PATCH`; otherwise, `false`.
559    pub fn is_patch(&self) -> bool {
560        self.get_method().is_patch()
561    }
562
563    /// Checks whether the request method is `HEAD`.
564    ///
565    /// - Returns: `true` if the method is `HEAD`; otherwise, `false`.
566    pub fn is_head(&self) -> bool {
567        self.get_method().is_head()
568    }
569
570    /// Checks whether the request method is `OPTIONS`.
571    ///
572    /// - Returns: `true` if the method is `OPTIONS`; otherwise, `false`.
573    pub fn is_options(&self) -> bool {
574        self.get_method().is_options()
575    }
576
577    /// Checks whether the request method is `CONNECT`.
578    ///
579    /// - Returns: `true` if the method is `CONNECT`; otherwise, `false`.
580    pub fn is_connect(&self) -> bool {
581        self.get_method().is_connect()
582    }
583
584    /// Checks whether the request method is `TRACE`.
585    ///
586    /// - Returns: `true` if the method is `TRACE`; otherwise, `false`.
587    pub fn is_trace(&self) -> bool {
588        self.get_method().is_trace()
589    }
590
591    /// Checks whether the request method is `UNKNOWN`.
592    ///
593    /// - Returns: `true` if the method is `UNKNOWN`; otherwise, `false`.
594    pub fn is_unknown_method(&self) -> bool {
595        self.get_method().is_unknown()
596    }
597
598    /// Determines if keep-alive connection should be enabled for this request.
599    ///
600    /// This function checks the Connection header and HTTP version to determine if
601    /// keep-alive should be enabled. The logic is as follows:
602    ///
603    /// 1. If Connection header exists:
604    ///    - Returns true if header value is "keep-alive"
605    ///    - Returns false if header value is "close"
606    /// 2. If no Connection header:
607    ///    - Returns true if HTTP version is 1.1 or higher
608    ///    - Returns false otherwise
609    ///
610    /// # Returns
611    /// - `bool`: true if keep-alive should be enabled, false otherwise
612    pub fn is_enable_keep_alive(&self) -> bool {
613        if let Some(connection_value) = self.get_header_back(CONNECTION) {
614            if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
615                return true;
616            } else if connection_value.eq_ignore_ascii_case(CLOSE) {
617                return self.is_ws();
618            }
619        }
620        self.is_http1_1_or_higher() || self.is_ws()
621    }
622}