http_type/request/
impl.rs

1use crate::*;
2
3impl Default for Request {
4    fn default() -> Self {
5        Self {
6            method: Methods::default(),
7            host: String::new(),
8            version: HttpVersion::default(),
9            path: String::new(),
10            querys: hash_map_xxhash3_64(),
11            headers: hash_map_xxhash3_64(),
12            body: Vec::new(),
13        }
14    }
15}
16
17impl Request {
18    /// Creates a new `Request` object from a TCP stream.
19    ///
20    /// # Parameters
21    /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`
22    /// - `buffer_size`: Request buffer size
23    ///
24    /// # Returns
25    /// - `Ok`: A `Request` object populated with the HTTP request data.
26    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
27    pub async fn http_from_reader(
28        reader: &mut BufReader<&mut TcpStream>,
29        buffer_size: usize,
30    ) -> RequestReaderHandleResult {
31        let mut request_line: String = String::with_capacity(buffer_size);
32        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
33        let parts: Vec<&str> = request_line.split_whitespace().collect();
34        if parts.len() < 3 {
35            return Err(RequestError::InvalidHttpRequest);
36        }
37        let method: RequestMethod = parts[0]
38            .to_string()
39            .parse::<RequestMethod>()
40            .unwrap_or_default();
41        let full_path: RequestPath = parts[1].to_string();
42        let version: RequestVersion = parts[2]
43            .to_string()
44            .parse::<RequestVersion>()
45            .unwrap_or_default();
46        let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
47        let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
48        let query_string: String = query_index.map_or(EMPTY_STR.to_owned(), |i| {
49            let temp: String = full_path[i + 1..].to_string();
50            if hash_index.is_none() || hash_index.unwrap() <= i {
51                return temp.into();
52            }
53            let data: String = temp
54                .split(HASH_SYMBOL)
55                .next()
56                .unwrap_or_default()
57                .to_string();
58            data.into()
59        });
60        let querys: RequestQuerys = Self::parse_querys(&query_string);
61        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
62            full_path[..i].to_string()
63        } else {
64            full_path
65        };
66        let mut headers: RequestHeaders = hash_map_xxhash3_64();
67        let mut host: RequestHost = EMPTY_STR.to_owned();
68        let mut content_length: usize = 0;
69        loop {
70            let mut header_line: String = String::with_capacity(buffer_size);
71            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
72            let header_line: &str = header_line.trim();
73            if header_line.is_empty() {
74                break;
75            }
76            let parts: Vec<&str> = header_line.splitn(2, COLON_SPACE_SYMBOL).collect();
77            if parts.len() != 2 {
78                continue;
79            }
80            let key: String = parts[0].trim().to_ascii_lowercase();
81            let value: String = parts[1].trim().to_string();
82            if key == HOST {
83                host = value.clone();
84            } else if key == CONTENT_LENGTH {
85                content_length = value.parse().unwrap_or(0);
86            }
87            headers.insert(key, value);
88        }
89        let mut body: RequestBody = vec![0; content_length];
90        if content_length > 0 {
91            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
92        }
93        Ok(Request {
94            method,
95            host,
96            version,
97            path,
98            querys,
99            headers,
100            body,
101        })
102    }
103
104    /// Creates a new `Request` object from a TCP stream.
105    ///
106    /// # Parameters
107    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
108    /// - `buffer_size`: Request buffer size
109    ///
110    /// # Returns
111    /// - `Ok`: A `Request` object populated with the HTTP request data.
112    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
113    pub async fn http_request_from_stream(
114        stream: &ArcRwLockStream,
115        buffer_size: usize,
116    ) -> RequestReaderHandleResult {
117        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
118        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
119        Self::http_from_reader(&mut reader, buffer_size).await
120    }
121
122    /// Creates a new `Request` object from a TCP stream.
123    ///
124    /// # Parameters
125    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
126    /// - `buffer_size`: Request buffer size
127    ///
128    /// # Returns
129    /// - `Ok`: A `Request` object populated with the HTTP request data.
130    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
131    pub async fn websocket_request_from_stream(
132        stream: &ArcRwLockStream,
133        buffer_size: usize,
134    ) -> RequestReaderHandleResult {
135        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
136        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
137        Self::websocket_from_reader(&mut reader, buffer_size).await
138    }
139
140    /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
141    ///
142    /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
143    /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
144    /// based on the received data. The request body is set using the received bytes.
145    ///
146    /// # Arguments
147    /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
148    ///   This reader is used to read the incoming WebSocket request data.
149    /// - `buffer_size`: - Request buffer size
150    ///
151    /// # Returns
152    /// - `Ok(Request)` - A `Request` object constructed from the received data.
153    ///   - If no data is read (`Ok(0)`), an empty `Request` object is returned.
154    ///   - If data is successfully read, the request body is set with the received bytes.
155    /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
156    pub async fn websocket_from_reader(
157        reader: &mut BufReader<&mut TcpStream>,
158        buffer_size: usize,
159    ) -> RequestReaderHandleResult {
160        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
161        let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
162        let mut full_frame: Vec<u8> = Vec::with_capacity(buffer_size);
163        loop {
164            let len: usize = match reader.read(&mut temp_buffer).await {
165                Ok(len) => len,
166                Err(_) => return Err(RequestError::InvalidWebSocketRequest),
167            };
168            if len == 0 {
169                break;
170            }
171            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
172            if let Some((frame, consumed)) =
173                WebSocketFrame::decode_websocket_frame_with_length(&dynamic_buffer)
174            {
175                dynamic_buffer.drain(0..consumed);
176                full_frame.extend_from_slice(frame.get_payload_data());
177                if *frame.get_fin() {
178                    let mut request: Request = Request::default();
179                    request.set_body(full_frame);
180                    return Ok(request);
181                }
182            }
183        }
184        Err(RequestError::InvalidWebSocketRequest)
185    }
186
187    /// Parse querys
188    ///
189    /// # Parameters
190    /// - `query`: &str
191    ///
192    /// # Returns
193    /// - RequestQuerys
194    fn parse_querys(query: &str) -> RequestQuerys {
195        let mut query_map: RequestQuerys = hash_map_xxhash3_64();
196        for pair in query.split(AND) {
197            let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
198            let key: String = parts.next().unwrap_or_default().to_string();
199            if key.is_empty() {
200                continue;
201            }
202            let value: String = parts.next().unwrap_or_default().to_string();
203            query_map.insert(key, value);
204        }
205        query_map
206    }
207
208    /// Retrieves the value of a query parameter by its key.
209    ///
210    /// # Parameters
211    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
212    ///
213    /// # Returns
214    /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
215    ///   or `None` if the key does not exist.
216    pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
217    where
218        K: Into<RequestQuerysKey>,
219    {
220        self.querys
221            .get(&key.into())
222            .and_then(|data| Some(data.clone()))
223    }
224
225    /// Retrieves the value of a request header by its key.
226    ///
227    /// # Parameters
228    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
229    ///
230    /// # Returns
231    /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
232    ///   or `None` if the key does not exist.
233    pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
234    where
235        K: Into<RequestHeadersKey>,
236    {
237        self.headers
238            .get(&key.into())
239            .and_then(|data| Some(data.clone()))
240    }
241
242    /// Retrieves the body content of the object as a UTF-8 encoded string.
243    ///
244    /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
245    /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
246    ///
247    /// # Returns
248    /// A `String` containing the body content.
249    pub fn get_body_string(&self) -> String {
250        String::from_utf8_lossy(self.get_body()).into_owned()
251    }
252
253    /// Deserializes the body content of the object into a specified type `T`.
254    ///
255    /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
256    /// It then attempts to deserialize the string into the specified type `T` using `serde_json::from_str`.
257    ///
258    /// # Type Parameters
259    /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
260    ///
261    /// # Returns
262    /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
263    /// - `Err(serde_json::Error)`: An error if the deserialization fails (e.g., invalid JSON format or type mismatch).
264    pub fn get_body_json<T>(&self) -> ResultSerdeJsonError<T>
265    where
266        T: DeserializeOwned,
267    {
268        json_parse_from_slice(self.get_body())
269    }
270
271    /// Adds a header to the request.
272    ///
273    /// This function inserts a key-value pair into the request headers.
274    /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
275    ///
276    /// # Parameters
277    /// - `key`: The header key, which will be converted into a `String`.
278    /// - `value`: The value of the header, which will be converted into a `String`.
279    ///
280    /// # Returns
281    /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
282    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
283    where
284        K: Into<String>,
285        V: Into<String>,
286    {
287        self.headers.insert(key.into(), value.into());
288        self
289    }
290
291    /// Set the body of the response.
292    ///
293    /// This method allows you to set the body of the response by converting the provided
294    /// value into a `RequestBody` type. The `body` is updated with the converted value,
295    /// and the method returns a mutable reference to the current instance for method chaining.
296    ///
297    /// # Parameters
298    /// - `body`: The body of the response to be set. It can be any type that can be converted
299    ///   into a `RequestBody` using the `Into` trait.
300    ///
301    /// # Return Value
302    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
303    /// Set the body of the response.
304    ///
305    /// This method allows you to set the body of the response by converting the provided
306    /// value into a `RequestBody` type. The `body` is updated with the converted value,
307    /// and the method returns a mutable reference to the current instance for method chaining.
308    ///
309    /// # Parameters
310    /// - `body`: The body of the response to be set. It can be any type that can be converted
311    ///   into a `RequestBody` using the `Into` trait.
312    ///
313    /// # Return Value
314    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
315    pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
316        self.body = body.into();
317        self
318    }
319
320    /// Set the HTTP method of the request.
321    ///
322    /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
323    /// by converting the provided value into a `RequestMethod` type. The `method` is updated
324    /// with the converted value, and the method returns a mutable reference to the current
325    /// instance for method chaining.
326    ///
327    /// # Parameters
328    /// - `method`: The HTTP method to be set for the request. It can be any type that can
329    ///   be converted into a `RequestMethod` using the `Into` trait.
330    ///
331    /// # Return Value
332    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
333    pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
334        self.method = method.into();
335        self
336    }
337
338    /// Set the host of the request.
339    ///
340    /// This method allows you to set the host (e.g., www.example.com) for the request
341    /// by converting the provided value into a `RequestHost` type. The `host` is updated
342    /// with the converted value, and the method returns a mutable reference to the current
343    /// instance for method chaining.
344    ///
345    /// # Parameters
346    /// - `host`: The host to be set for the request. It can be any type that can be converted
347    ///   into a `RequestHost` using the `Into` trait.
348    ///
349    /// # Return Value
350    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
351    pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
352        self.host = host.into();
353        self
354    }
355
356    /// Set the path of the request.
357    ///
358    /// This method allows you to set the path (e.g., /api/v1/resource) for the request
359    /// by converting the provided value into a `RequestPath` type. The `path` is updated
360    /// with the converted value, and the method returns a mutable reference to the current
361    /// instance for method chaining.
362    ///
363    /// # Parameters
364    /// - `path`: The path to be set for the request. It can be any type that can be converted
365    ///   into a `RequestPath` using the `Into` trait.
366    ///
367    /// # Return Value
368    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
369    pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
370        self.path = path.into();
371        self
372    }
373
374    /// Sets a query parameter for the request.
375    ///
376    /// # Parameters
377    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
378    /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
379    ///
380    /// # Returns
381    /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
382    pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
383        &mut self,
384        key: K,
385        value: V,
386    ) -> &mut Self {
387        self.querys.insert(key.into(), value.into());
388        self
389    }
390
391    /// Converts the request to a formatted string representation.
392    ///
393    /// - Returns: A `String` containing formatted request details.
394    pub fn get_string(&self) -> String {
395        let body: &Vec<u8> = self.get_body();
396        format!(
397            "[Request] => [Method]: {}; [Host]: {}; [Version]: {}; [Path]: {}; [Querys]: {:?}; [Headers]: {:?}; [Body]: {};",
398            self.get_method(),
399            self.get_host(),
400            self.get_version(),
401            self.get_path(),
402            self.get_querys(),
403            self.get_headers(),
404            body_to_string(body),
405        )
406    }
407
408    /// Retrieves the upgrade type from the request headers.
409    ///
410    /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
411    ///            If the header is missing or invalid, returns the default `UpgradeType`.
412    pub fn get_upgrade_type(&self) -> UpgradeType {
413        let upgrade_type: UpgradeType = self
414            .get_header(UPGRADE)
415            .and_then(|data| data.parse::<UpgradeType>().ok())
416            .unwrap_or_default();
417        upgrade_type
418    }
419
420    /// Determines if keep-alive connection should be enabled for this request.
421    ///
422    /// This function checks the Connection header and HTTP version to determine if
423    /// keep-alive should be enabled. The logic is as follows:
424    ///
425    /// 1. If Connection header exists:
426    ///    - Returns true if header value is "keep-alive"
427    ///    - Returns false if header value is "close"
428    /// 2. If no Connection header:
429    ///    - Returns true if HTTP version is 1.1 or higher
430    ///    - Returns false otherwise
431    ///
432    /// # Returns
433    /// - `bool`: true if keep-alive should be enabled, false otherwise
434    pub fn is_enable_keep_alive(&self) -> bool {
435        if let Some(connection_value) = self.get_header(CONNECTION) {
436            let connection_value_lowercase: String = connection_value.to_ascii_lowercase();
437            if connection_value_lowercase == CONNECTION_KEEP_ALIVE {
438                return true;
439            } else if connection_value_lowercase == CONNECTION_CLOSE {
440                return false;
441            }
442        }
443        self.get_version().is_http1_1_or_higher()
444    }
445
446    /// Determines if keep-alive connection should be disabled for this request.
447    ///
448    /// This is the inverse of `is_enable_keep_alive()`. It returns true when
449    /// keep-alive should be disabled, and false when it should be enabled.
450    ///
451    /// # Returns
452    /// - `bool`: true if keep-alive should be disabled, false otherwise
453    pub fn is_disable_keep_alive(&self) -> bool {
454        !self.is_enable_keep_alive()
455    }
456}