http_type/request/
impl.rs

1use crate::*;
2
3impl Default for Request {
4    #[inline]
5    fn default() -> Self {
6        Self {
7            method: Methods::default(),
8            host: String::new(),
9            version: HttpVersion::default(),
10            path: String::new(),
11            querys: RequestQuerys::new(),
12            headers: RequestHeaders::new(),
13            body: Vec::new(),
14        }
15    }
16}
17
18impl Request {
19    /// Creates a new `Request` object from a TCP stream.
20    ///
21    /// # Parameters
22    /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`
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    #[inline]
28    pub async fn http_from_reader(reader: &mut BufReader<&mut TcpStream>) -> RequestNewResult {
29        let mut request_line: String = String::new();
30        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
31        let parts: Vec<&str> = request_line.split_whitespace().collect();
32        if parts.len() < 3 {
33            return Err(RequestError::InvalidHttpRequest);
34        }
35        let method: RequestMethod = parts[0]
36            .to_string()
37            .parse::<RequestMethod>()
38            .unwrap_or_default();
39        let full_path: RequestPath = parts[1].to_string();
40        let version: RequestVersion = parts[2]
41            .to_string()
42            .parse::<RequestVersion>()
43            .unwrap_or_default();
44        let hash_index: Option<usize> = full_path.find(HASH_SYMBOL);
45        let query_index: Option<usize> = full_path.find(QUERY_SYMBOL);
46        let query_string: String = query_index.map_or(EMPTY_STR.to_owned(), |i| {
47            let temp: String = full_path[i + 1..].to_string();
48            if hash_index.is_none() || hash_index.unwrap() <= i {
49                return temp.into();
50            }
51            let data: String = temp
52                .split(HASH_SYMBOL)
53                .next()
54                .unwrap_or_default()
55                .to_string();
56            data.into()
57        });
58        let querys: RequestQuerys = Self::parse_querys(&query_string);
59        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
60            full_path[..i].to_string()
61        } else {
62            full_path
63        };
64        let mut headers: RequestHeaders = RequestHeaders::new();
65        let mut host: RequestHost = EMPTY_STR.to_owned();
66        let mut content_length: usize = 0;
67        loop {
68            let mut header_line: String = String::new();
69            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
70            let header_line: &str = header_line.trim();
71            if header_line.is_empty() {
72                break;
73            }
74            let parts: Vec<&str> = header_line.splitn(2, COLON_SPACE_SYMBOL).collect();
75            if parts.len() != 2 {
76                continue;
77            }
78            let key: String = parts[0].trim().to_string();
79            let value: String = parts[1].trim().to_string();
80            if key.eq_ignore_ascii_case(HOST) {
81                host = value.to_string();
82            }
83            if key.eq_ignore_ascii_case(CONTENT_LENGTH) {
84                content_length = value.parse().unwrap_or(0);
85            }
86            headers.insert(key, value);
87        }
88        let mut body: RequestBody = vec![0; content_length];
89        if content_length > 0 {
90            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
91        }
92        Ok(Request {
93            method,
94            host,
95            version,
96            path,
97            querys,
98            headers,
99            body,
100        })
101    }
102
103    /// Creates a new `Request` object from a TCP stream.
104    ///
105    /// # Parameters
106    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
107    ///
108    /// # Returns
109    /// - `Ok`: A `Request` object populated with the HTTP request data.
110    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
111    #[inline]
112    pub async fn http_request_from_stream(stream: &ArcRwLockStream) -> RequestNewResult {
113        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
114        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
115        Self::http_from_reader(&mut reader).await
116    }
117
118    /// Creates a new `Request` object from a TCP stream.
119    ///
120    /// # Parameters
121    /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
122    /// - `buffer_size`: Request buffer size
123    ///
124    /// # Returns
125    /// - `Ok`: A `Request` object populated with the HTTP request data.
126    /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
127    #[inline]
128    pub async fn websocket_request_from_stream(
129        stream: &ArcRwLockStream,
130        buffer_size: usize,
131    ) -> RequestNewResult {
132        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
133        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
134        Self::websocket_from_reader(&mut reader, buffer_size).await
135    }
136
137    /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
138    ///
139    /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
140    /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
141    /// based on the received data. The request body is set using the received bytes.
142    ///
143    /// # Arguments
144    /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
145    ///   This reader is used to read the incoming WebSocket request data.
146    /// - `buffer_size`: - Request buffer size
147    ///
148    /// # Returns
149    /// - `Ok(Request)` - A `Request` object constructed from the received data.
150    ///   - If no data is read (`Ok(0)`), an empty `Request` object is returned.
151    ///   - If data is successfully read, the request body is set with the received bytes.
152    /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
153    #[inline]
154    pub async fn websocket_from_reader(
155        reader: &mut BufReader<&mut TcpStream>,
156        buffer_size: usize,
157    ) -> RequestNewResult {
158        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
159        let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
160        let mut full_frame: Vec<u8> = Vec::with_capacity(buffer_size);
161        loop {
162            let len: usize = match reader.read(&mut temp_buffer).await {
163                Ok(len) => len,
164                Err(_) => return Err(RequestError::InvalidWebSocketRequest),
165            };
166            if len == 0 {
167                break;
168            }
169            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
170            if let Some((frame, consumed)) =
171                WebSocketFrame::decode_websocket_frame_with_length(&dynamic_buffer)
172            {
173                dynamic_buffer.drain(0..consumed);
174                full_frame.extend_from_slice(frame.get_payload_data());
175                if *frame.get_fin() {
176                    let mut request: Request = Request::default();
177                    request.set_body(full_frame);
178                    return Ok(request);
179                }
180            }
181        }
182        Err(RequestError::InvalidWebSocketRequest)
183    }
184
185    /// Parse querys
186    ///
187    /// # Parameters
188    /// - `query`: &str
189    ///
190    /// # Returns
191    /// - RequestQuerys
192    #[inline]
193    fn parse_querys(query: &str) -> RequestQuerys {
194        let mut query_map: RequestQuerys = RequestQuerys::new();
195        for pair in query.split(AND) {
196            let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
197            let key: String = parts.next().unwrap_or_default().to_string();
198            let value: String = parts.next().unwrap_or_default().to_string();
199            if !key.is_empty() {
200                query_map.insert(key, value);
201            }
202        }
203        query_map
204    }
205
206    /// Retrieves the value of a query parameter by its key.
207    ///
208    /// # Parameters
209    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
210    ///
211    /// # Returns
212    /// - `Option<RequestQuerysValue>`: Returns `Some(value)` if the key exists in the query parameters,
213    ///   or `None` if the key does not exist.
214    #[inline]
215    pub fn get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
216    where
217        K: Into<RequestQuerysKey>,
218    {
219        self.querys
220            .get(&key.into())
221            .and_then(|data| Some(data.clone()))
222    }
223
224    /// Retrieves the value of a request header by its key.
225    ///
226    /// # Parameters
227    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
228    ///
229    /// # Returns
230    /// - `Option<RequestHeadersValue>`: Returns `Some(value)` if the key exists in the request headers,
231    ///   or `None` if the key does not exist.
232    #[inline]
233    pub fn get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
234    where
235        K: Into<RequestHeadersKey>,
236    {
237        self.headers
238            .get(&key.into())
239            .and_then(|data| Some(data.clone()))
240    }
241
242    /// Adds a header to the request.
243    ///
244    /// This function inserts a key-value pair into the request headers.
245    /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
246    ///
247    /// # Parameters
248    /// - `key`: The header key, which will be converted into a `String`.
249    /// - `value`: The value of the header, which will be converted into a `String`.
250    ///
251    /// # Returns
252    /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
253    #[inline]
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    #[inline]
288    pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
289        self.body = body.into();
290        self
291    }
292
293    /// Set the HTTP method of the request.
294    ///
295    /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
296    /// by converting the provided value into a `RequestMethod` type. The `method` is updated
297    /// with the converted value, and the method returns a mutable reference to the current
298    /// instance for method chaining.
299    ///
300    /// # Parameters
301    /// - `method`: The HTTP method to be set for the request. It can be any type that can
302    ///   be converted into a `RequestMethod` using the `Into` trait.
303    ///
304    /// # Return Value
305    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
306    #[inline]
307    pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
308        self.method = method.into();
309        self
310    }
311
312    /// Set the host of the request.
313    ///
314    /// This method allows you to set the host (e.g., www.example.com) for the request
315    /// by converting the provided value into a `RequestHost` type. The `host` is updated
316    /// with the converted value, and the method returns a mutable reference to the current
317    /// instance for method chaining.
318    ///
319    /// # Parameters
320    /// - `host`: The host to be set for the request. It can be any type that can be converted
321    ///   into a `RequestHost` using the `Into` trait.
322    ///
323    /// # Return Value
324    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
325    #[inline]
326    pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
327        self.host = host.into();
328        self
329    }
330
331    /// Set the path of the request.
332    ///
333    /// This method allows you to set the path (e.g., /api/v1/resource) for the request
334    /// by converting the provided value into a `RequestPath` type. The `path` is updated
335    /// with the converted value, and the method returns a mutable reference to the current
336    /// instance for method chaining.
337    ///
338    /// # Parameters
339    /// - `path`: The path to be set for the request. It can be any type that can be converted
340    ///   into a `RequestPath` using the `Into` trait.
341    ///
342    /// # Return Value
343    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
344    #[inline]
345    pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
346        self.path = path.into();
347        self
348    }
349
350    /// Sets a query parameter for the request.
351    ///
352    /// # Parameters
353    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
354    /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
355    ///
356    /// # Returns
357    /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
358    #[inline]
359    pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
360        &mut self,
361        key: K,
362        value: V,
363    ) -> &mut Self {
364        self.querys.insert(key.into(), value.into());
365        self
366    }
367
368    /// Converts the request to a formatted string representation.
369    ///
370    /// - Returns: A `String` containing formatted request details.
371    #[inline]
372    pub fn get_string(&self) -> String {
373        let body: &Vec<u8> = self.get_body();
374        format!(
375            "[Request] => [Method]: {}; [Host]: {}; [Version]: {}; [Path]: {}; [Querys]: {:?}; [Headers]: {:?}; [Body]: {};",
376            self.get_method(),
377            self.get_host(),
378            self.get_version(),
379            self.get_path(),
380            self.get_querys(),
381            self.get_headers(),
382            body_to_string(body),
383        )
384    }
385
386    /// Retrieves the upgrade type from the request headers.
387    ///
388    /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
389    ///            If the header is missing or invalid, returns the default `UpgradeType`.
390    #[inline]
391    pub fn get_upgrade_type(&self) -> UpgradeType {
392        let upgrade_type: UpgradeType = self
393            .get_header(UPGRADE)
394            .and_then(|data| data.parse::<UpgradeType>().ok())
395            .unwrap_or_default();
396        upgrade_type
397    }
398}