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