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}