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}