http_type/request/
impl.rs

1use super::error::Error;
2use crate::*;
3
4impl Default for Request {
5    #[inline]
6    fn default() -> Self {
7        Self {
8            method: Methods::default(),
9            host: String::new(),
10            version: HttpVersion::default(),
11            path: String::new(),
12            querys: HashMap::new(),
13            headers: HashMap::new(),
14            body: Vec::new(),
15            upgrade_type: UpgradeType::default(),
16        }
17    }
18}
19
20impl fmt::Display for Request {
21    #[inline]
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        write!(f, "{:?}", self)
24    }
25}
26
27impl Request {
28    /// Creates a new `Request` object from a TCP stream.
29    ///
30    /// # Parameters
31    /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`
32    ///
33    /// # Returns
34    /// - `Ok`: A `Request` object populated with the HTTP request data.
35    /// - `Err`: An `Error` if the request is invalid or cannot be read.
36    #[inline]
37    pub async fn from_reader(reader: &mut BufReader<&mut TcpStream>) -> RequestNewResult {
38        let mut request_line: String = String::new();
39        let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
40        let parts: Vec<&str> = request_line.split_whitespace().collect();
41        if parts.len() < 3 {
42            return Err(Error::InvalidHttpRequest);
43        }
44        let method: RequestMethod = parts[0]
45            .to_string()
46            .parse::<RequestMethod>()
47            .unwrap_or_default();
48        let full_path: RequestPath = parts[1].to_string();
49        let version: RequestVersion = parts[2]
50            .to_string()
51            .parse::<RequestVersion>()
52            .unwrap_or_default();
53        let hash_index: Option<usize> = full_path.find(HASH_SYMBOL);
54        let query_index: Option<usize> = full_path.find(QUERY_SYMBOL);
55        let query_string: String = query_index.map_or(EMPTY_STR.to_owned(), |i| {
56            let temp: String = full_path[i + 1..].to_string();
57            if hash_index.is_none() || hash_index.unwrap() <= i {
58                return temp.into();
59            }
60            let data: String = temp
61                .split(HASH_SYMBOL)
62                .next()
63                .unwrap_or_default()
64                .to_string();
65            data.into()
66        });
67        let querys: RequestQuerys = Self::parse_querys(&query_string);
68        let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
69            full_path[..i].to_string()
70        } else {
71            full_path
72        };
73        let mut headers: RequestHeaders = HashMap::new();
74        let mut host: RequestHost = EMPTY_STR.to_owned();
75        let mut content_length: usize = 0;
76        loop {
77            let mut header_line: String = String::new();
78            let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
79            let header_line: &str = header_line.trim();
80            if header_line.is_empty() {
81                break;
82            }
83            let parts: Vec<&str> = header_line.splitn(2, COLON_SPACE_SYMBOL).collect();
84            if parts.len() != 2 {
85                continue;
86            }
87            let key: String = parts[0].trim().to_string();
88            let value: String = parts[1].trim().to_string();
89            if key.eq_ignore_ascii_case(HOST) {
90                host = value.to_string();
91            }
92            if key.eq_ignore_ascii_case(CONTENT_LENGTH) {
93                content_length = value.parse().unwrap_or(0);
94            }
95            headers.insert(key, value);
96        }
97        let mut body: RequestBody = Vec::new();
98        if content_length > 0 {
99            body.resize(content_length, 0);
100            let _ = AsyncReadExt::read_exact(reader, &mut body).await;
101        }
102        let upgrade_type: UpgradeType = headers
103            .get(UPGRADE)
104            .and_then(|data| data.parse::<UpgradeType>().ok())
105            .unwrap_or_default();
106        Ok(Request {
107            method,
108            host,
109            version,
110            path,
111            querys,
112            headers,
113            body,
114            upgrade_type,
115        })
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    /// - `is_websocket`: Is websocket
123    ///
124    /// # Returns
125    /// - `Ok`: A `Request` object populated with the HTTP request data.
126    /// - `Err`: An `Error` if the request is invalid or cannot be read.
127    #[inline]
128    pub async fn from_stream(stream: &ArcRwLockStream, is_websocket: bool) -> RequestNewResult {
129        let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
130        let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
131        if is_websocket {
132            Self::from_ws_reader(&mut reader).await
133        } else {
134            Self::from_reader(&mut reader).await
135        }
136    }
137
138    /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
139    ///
140    /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
141    /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
142    /// based on the received data. The request body is set using the received bytes.
143    ///
144    /// # Arguments
145    /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
146    ///   This reader is used to read the incoming WebSocket request data.
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 from_ws_reader(reader: &mut BufReader<&mut TcpStream>) -> RequestNewResult {
155        let mut buffer = [0; 1024];
156        let mut request: Request = Request::default();
157        match reader.read(&mut buffer).await {
158            Ok(0) => Ok(request),
159            Ok(n) => {
160                request.set_body(&mut buffer[..n]);
161                return Ok(request);
162            }
163            Err(_) => Err(RequestError::InvalidWebSocketRequest),
164        }
165    }
166
167    /// Parse querys
168    ///
169    /// # Parameters
170    /// - `query`: &str
171    ///
172    /// # Returns
173    /// - RequestQuerys
174    #[inline]
175    fn parse_querys(query: &str) -> RequestQuerys {
176        let mut query_map: RequestQuerys = HashMap::new();
177        for pair in query.split(AND) {
178            let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
179            let key: String = parts.next().unwrap_or_default().to_string();
180            let value: String = parts.next().unwrap_or_default().to_string();
181            if !key.is_empty() {
182                query_map.insert(key, value);
183            }
184        }
185        query_map
186    }
187
188    /// Retrieves the value of a query parameter by its key.
189    ///
190    /// # Parameters
191    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
192    ///
193    /// # Returns
194    /// - `Option<RequestQuerysValue>`: Returns `Some(value)` if the key exists in the query parameters,
195    ///   or `None` if the key does not exist.
196    #[inline]
197    pub fn get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
198    where
199        K: Into<RequestQuerysKey>,
200    {
201        self.querys
202            .get(&key.into())
203            .and_then(|data| Some(data.clone()))
204    }
205
206    /// Retrieves the value of a request header by its key.
207    ///
208    /// # Parameters
209    /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
210    ///
211    /// # Returns
212    /// - `Option<RequestHeadersValue>`: Returns `Some(value)` if the key exists in the request headers,
213    ///   or `None` if the key does not exist.
214    #[inline]
215    pub fn get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
216    where
217        K: Into<RequestHeadersKey>,
218    {
219        self.headers
220            .get(&key.into())
221            .and_then(|data| Some(data.clone()))
222    }
223
224    /// Adds a header to the request.
225    ///
226    /// This function inserts a key-value pair into the request headers.
227    /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
228    ///
229    /// # Parameters
230    /// - `key`: The header key, which will be converted into a `String`.
231    /// - `value`: The value of the header, which will be converted into a `String`.
232    ///
233    /// # Returns
234    /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
235    #[inline]
236    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
237    where
238        K: Into<String>,
239        V: Into<String>,
240    {
241        self.headers.insert(key.into(), value.into());
242        self
243    }
244
245    /// Set the body of the response.
246    ///
247    /// This method allows you to set the body of the response by converting the provided
248    /// value into a `RequestBody` type. The `body` is updated with the converted value,
249    /// and the method returns a mutable reference to the current instance for method chaining.
250    ///
251    /// # Parameters
252    /// - `body`: The body of the response to be set. It can be any type that can be converted
253    ///   into a `RequestBody` using the `Into` trait.
254    ///
255    /// # Return Value
256    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
257    /// Set the body of the response.
258    ///
259    /// This method allows you to set the body of the response by converting the provided
260    /// value into a `RequestBody` type. The `body` is updated with the converted value,
261    /// and the method returns a mutable reference to the current instance for method chaining.
262    ///
263    /// # Parameters
264    /// - `body`: The body of the response to be set. It can be any type that can be converted
265    ///   into a `RequestBody` using the `Into` trait.
266    ///
267    /// # Return Value
268    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
269    #[inline]
270    pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
271        self.body = body.into();
272        self
273    }
274
275    /// Set the HTTP method of the request.
276    ///
277    /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
278    /// by converting the provided value into a `RequestMethod` type. The `method` is updated
279    /// with the converted value, and the method returns a mutable reference to the current
280    /// instance for method chaining.
281    ///
282    /// # Parameters
283    /// - `method`: The HTTP method to be set for the request. It can be any type that can
284    ///   be converted into a `RequestMethod` using the `Into` trait.
285    ///
286    /// # Return Value
287    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
288    #[inline]
289    pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
290        self.method = method.into();
291        self
292    }
293
294    /// Set the host of the request.
295    ///
296    /// This method allows you to set the host (e.g., www.example.com) for the request
297    /// by converting the provided value into a `RequestHost` type. The `host` is updated
298    /// with the converted value, and the method returns a mutable reference to the current
299    /// instance for method chaining.
300    ///
301    /// # Parameters
302    /// - `host`: The host to be set for the request. It can be any type that can be converted
303    ///   into a `RequestHost` using the `Into` trait.
304    ///
305    /// # Return Value
306    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
307    #[inline]
308    pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
309        self.host = host.into();
310        self
311    }
312
313    /// Set the path of the request.
314    ///
315    /// This method allows you to set the path (e.g., /api/v1/resource) for the request
316    /// by converting the provided value into a `RequestPath` type. The `path` is updated
317    /// with the converted value, and the method returns a mutable reference to the current
318    /// instance for method chaining.
319    ///
320    /// # Parameters
321    /// - `path`: The path to be set for the request. It can be any type that can be converted
322    ///   into a `RequestPath` using the `Into` trait.
323    ///
324    /// # Return Value
325    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
326    #[inline]
327    pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
328        self.path = path.into();
329        self
330    }
331
332    /// Sets a query parameter for the request.
333    ///
334    /// # Parameters
335    /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
336    /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
337    ///
338    /// # Returns
339    /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
340    #[inline]
341    pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
342        &mut self,
343        key: K,
344        value: V,
345    ) -> &mut Self {
346        self.querys.insert(key.into(), value.into());
347        self
348    }
349}