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    ) -> RequestNewResult {
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.to_string();
84            }
85            if key == CONTENT_LENGTH {
86                content_length = value.parse().unwrap_or(0);
87            }
88            headers.insert(key, value);
89        }
90        let mut body: RequestBody = vec![0; content_length];
91        if content_length > 0 {
92            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
93        }
94        Ok(Request {
95            method,
96            host,
97            version,
98            path,
99            querys,
100            headers,
101            body,
102        })
103    }
104
105    /// Creates a new `Request` object from a TCP stream.
106    ///
107    /// # Parameters
108    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
109    /// - `buffer_size`: Request buffer size
110    ///
111    /// # Returns
112    /// - `Ok`: A `Request` object populated with the HTTP request data.
113    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
114    pub async fn http_request_from_stream(
115        stream: &ArcRwLockStream,
116        buffer_size: usize,
117    ) -> RequestNewResult {
118        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
119        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
120        Self::http_from_reader(&mut reader, buffer_size).await
121    }
122
123    /// Creates a new `Request` object from a TCP stream.
124    ///
125    /// # Parameters
126    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
127    /// - `buffer_size`: Request buffer size
128    ///
129    /// # Returns
130    /// - `Ok`: A `Request` object populated with the HTTP request data.
131    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
132    pub async fn websocket_request_from_stream(
133        stream: &ArcRwLockStream,
134        buffer_size: usize,
135    ) -> RequestNewResult {
136        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
137        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
138        Self::websocket_from_reader(&mut reader, buffer_size).await
139    }
140
141    /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
142    ///
143    /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
144    /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
145    /// based on the received data. The request body is set using the received bytes.
146    ///
147    /// # Arguments
148    /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
149    ///   This reader is used to read the incoming WebSocket request data.
150    /// - `buffer_size`: - Request buffer size
151    ///
152    /// # Returns
153    /// - `Ok(Request)` - A `Request` object constructed from the received data.
154    ///   - If no data is read (`Ok(0)`), an empty `Request` object is returned.
155    ///   - If data is successfully read, the request body is set with the received bytes.
156    /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
157    pub async fn websocket_from_reader(
158        reader: &mut BufReader<&mut TcpStream>,
159        buffer_size: usize,
160    ) -> RequestNewResult {
161        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
162        let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
163        let mut full_frame: Vec<u8> = Vec::with_capacity(buffer_size);
164        loop {
165            let len: usize = match reader.read(&mut temp_buffer).await {
166                Ok(len) => len,
167                Err(_) => return Err(RequestError::InvalidWebSocketRequest),
168            };
169            if len == 0 {
170                break;
171            }
172            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
173            if let Some((frame, consumed)) =
174                WebSocketFrame::decode_websocket_frame_with_length(&dynamic_buffer)
175            {
176                dynamic_buffer.drain(0..consumed);
177                full_frame.extend_from_slice(frame.get_payload_data());
178                if *frame.get_fin() {
179                    let mut request: Request = Request::default();
180                    request.set_body(full_frame);
181                    return Ok(request);
182                }
183            }
184        }
185        Err(RequestError::InvalidWebSocketRequest)
186    }
187
188    /// Parse querys
189    ///
190    /// # Parameters
191    /// - `query`: &str
192    ///
193    /// # Returns
194    /// - RequestQuerys
195    fn parse_querys(query: &str) -> RequestQuerys {
196        let mut query_map: RequestQuerys = hash_map_xxhash3_64();
197        for pair in query.split(AND) {
198            let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
199            let key: String = parts.next().unwrap_or_default().to_string();
200            if key.is_empty() {
201                continue;
202            }
203            let value: String = parts.next().unwrap_or_default().to_string();
204            query_map.insert(key, value);
205        }
206        query_map
207    }
208
209    /// Retrieves the value of a query parameter by its key.
210    ///
211    /// # Parameters
212    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
213    ///
214    /// # Returns
215    /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
216    ///   or `None` if the key does not exist.
217    pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
218    where
219        K: Into<RequestQuerysKey>,
220    {
221        self.querys
222            .get(&key.into())
223            .and_then(|data| Some(data.clone()))
224    }
225
226    /// Retrieves the value of a request header by its key.
227    ///
228    /// # Parameters
229    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
230    ///
231    /// # Returns
232    /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
233    ///   or `None` if the key does not exist.
234    pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
235    where
236        K: Into<RequestHeadersKey>,
237    {
238        self.headers
239            .get(&key.into())
240            .and_then(|data| Some(data.clone()))
241    }
242
243    /// Adds a header to the request.
244    ///
245    /// This function inserts a key-value pair into the request headers.
246    /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
247    ///
248    /// # Parameters
249    /// - `key`: The header key, which will be converted into a `String`.
250    /// - `value`: The value of the header, which will be converted into a `String`.
251    ///
252    /// # Returns
253    /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
254    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
255    where
256        K: Into<String>,
257        V: Into<String>,
258    {
259        self.headers.insert(key.into(), value.into());
260        self
261    }
262
263    /// Set the body of the response.
264    ///
265    /// This method allows you to set the body of the response by converting the provided
266    /// value into a `RequestBody` type. The `body` is updated with the converted value,
267    /// and the method returns a mutable reference to the current instance for method chaining.
268    ///
269    /// # Parameters
270    /// - `body`: The body of the response to be set. It can be any type that can be converted
271    ///   into a `RequestBody` using the `Into` trait.
272    ///
273    /// # Return Value
274    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
275    /// Set the body of the response.
276    ///
277    /// This method allows you to set the body of the response by converting the provided
278    /// value into a `RequestBody` type. The `body` is updated with the converted value,
279    /// and the method returns a mutable reference to the current instance for method chaining.
280    ///
281    /// # Parameters
282    /// - `body`: The body of the response to be set. It can be any type that can be converted
283    ///   into a `RequestBody` using the `Into` trait.
284    ///
285    /// # Return Value
286    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
287    pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
288        self.body = body.into();
289        self
290    }
291
292    /// Set the HTTP method of the request.
293    ///
294    /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
295    /// by converting the provided value into a `RequestMethod` type. The `method` is updated
296    /// with the converted value, and the method returns a mutable reference to the current
297    /// instance for method chaining.
298    ///
299    /// # Parameters
300    /// - `method`: The HTTP method to be set for the request. It can be any type that can
301    ///   be converted into a `RequestMethod` using the `Into` trait.
302    ///
303    /// # Return Value
304    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
305    pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
306        self.method = method.into();
307        self
308    }
309
310    /// Set the host of the request.
311    ///
312    /// This method allows you to set the host (e.g., www.example.com) for the request
313    /// by converting the provided value into a `RequestHost` type. The `host` is updated
314    /// with the converted value, and the method returns a mutable reference to the current
315    /// instance for method chaining.
316    ///
317    /// # Parameters
318    /// - `host`: The host to be set for the request. It can be any type that can be converted
319    ///   into a `RequestHost` using the `Into` trait.
320    ///
321    /// # Return Value
322    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
323    pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
324        self.host = host.into();
325        self
326    }
327
328    /// Set the path of the request.
329    ///
330    /// This method allows you to set the path (e.g., /api/v1/resource) for the request
331    /// by converting the provided value into a `RequestPath` type. The `path` is updated
332    /// with the converted value, and the method returns a mutable reference to the current
333    /// instance for method chaining.
334    ///
335    /// # Parameters
336    /// - `path`: The path to be set for the request. It can be any type that can be converted
337    ///   into a `RequestPath` using the `Into` trait.
338    ///
339    /// # Return Value
340    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
341    pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
342        self.path = path.into();
343        self
344    }
345
346    /// Sets a query parameter for the request.
347    ///
348    /// # Parameters
349    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
350    /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
351    ///
352    /// # Returns
353    /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
354    pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
355        &mut self,
356        key: K,
357        value: V,
358    ) -> &mut Self {
359        self.querys.insert(key.into(), value.into());
360        self
361    }
362
363    /// Converts the request to a formatted string representation.
364    ///
365    /// - Returns: A `String` containing formatted request details.
366    pub fn get_string(&self) -> String {
367        let body: &Vec<u8> = self.get_body();
368        format!(
369            "[Request] => [Method]: {}; [Host]: {}; [Version]: {}; [Path]: {}; [Querys]: {:?}; [Headers]: {:?}; [Body]: {};",
370            self.get_method(),
371            self.get_host(),
372            self.get_version(),
373            self.get_path(),
374            self.get_querys(),
375            self.get_headers(),
376            body_to_string(body),
377        )
378    }
379
380    /// Retrieves the upgrade type from the request headers.
381    ///
382    /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
383    ///            If the header is missing or invalid, returns the default `UpgradeType`.
384    pub fn get_upgrade_type(&self) -> UpgradeType {
385        let upgrade_type: UpgradeType = self
386            .get_header(UPGRADE)
387            .and_then(|data| data.parse::<UpgradeType>().ok())
388            .unwrap_or_default();
389        upgrade_type
390    }
391}