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_xx_hash3_64(),
11 headers: hash_map_xx_hash3_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 ) -> RequestReaderHandleResult {
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_xx_hash3_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.clone();
84 } else if key == CONTENT_LENGTH {
85 content_length = value.parse().unwrap_or(0);
86 }
87 headers.insert(key, value);
88 }
89 let mut body: RequestBody = vec![0; content_length];
90 if content_length > 0 {
91 let _ = AsyncReadExt::read_exact(reader, &mut body).await;
92 }
93 Ok(Request {
94 method,
95 host,
96 version,
97 path,
98 querys,
99 headers,
100 body,
101 })
102 }
103
104 /// Creates a new `Request` object from a TCP stream.
105 ///
106 /// # Parameters
107 /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
108 /// - `buffer_size`: Request buffer size
109 ///
110 /// # Returns
111 /// - `Ok`: A `Request` object populated with the HTTP request data.
112 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
113 pub async fn http_request_from_stream(
114 stream: &ArcRwLockStream,
115 buffer_size: usize,
116 ) -> RequestReaderHandleResult {
117 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
118 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
119 Self::http_from_reader(&mut reader, buffer_size).await
120 }
121
122 /// Creates a new `Request` object from a TCP stream.
123 ///
124 /// # Parameters
125 /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
126 /// - `buffer_size`: Request buffer size
127 ///
128 /// # Returns
129 /// - `Ok`: A `Request` object populated with the HTTP request data.
130 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
131 pub async fn websocket_request_from_stream(
132 stream: &ArcRwLockStream,
133 buffer_size: usize,
134 ) -> RequestReaderHandleResult {
135 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
136 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
137 Self::websocket_from_reader(&mut reader, buffer_size).await
138 }
139
140 /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
141 ///
142 /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
143 /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
144 /// based on the received data. The request body is set using the received bytes.
145 ///
146 /// # Arguments
147 /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
148 /// This reader is used to read the incoming WebSocket request data.
149 /// - `buffer_size`: - Request buffer size
150 ///
151 /// # Returns
152 /// - `Ok(Request)` - A `Request` object constructed from the received data.
153 /// - If no data is read (`Ok(0)`), an empty `Request` object is returned.
154 /// - If data is successfully read, the request body is set with the received bytes.
155 /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
156 pub async fn websocket_from_reader(
157 reader: &mut BufReader<&mut TcpStream>,
158 buffer_size: usize,
159 ) -> RequestReaderHandleResult {
160 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
161 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
162 let mut full_frame: Vec<u8> = Vec::with_capacity(buffer_size);
163 loop {
164 let len: usize = match reader.read(&mut temp_buffer).await {
165 Ok(len) => len,
166 Err(_) => return Err(RequestError::InvalidWebSocketRequest),
167 };
168 if len == 0 {
169 break;
170 }
171 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
172 if let Some((frame, consumed)) =
173 WebSocketFrame::decode_websocket_frame_with_length(&dynamic_buffer)
174 {
175 dynamic_buffer.drain(0..consumed);
176 full_frame.extend_from_slice(frame.get_payload_data());
177 if *frame.get_fin() {
178 let mut request: Request = Request::default();
179 request.set_body(full_frame);
180 return Ok(request);
181 }
182 }
183 }
184 Err(RequestError::InvalidWebSocketRequest)
185 }
186
187 /// Parse querys
188 ///
189 /// # Parameters
190 /// - `query`: &str
191 ///
192 /// # Returns
193 /// - RequestQuerys
194 fn parse_querys(query: &str) -> RequestQuerys {
195 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
196 for pair in query.split(AND) {
197 let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
198 let key: String = parts.next().unwrap_or_default().to_string();
199 if key.is_empty() {
200 continue;
201 }
202 let value: String = parts.next().unwrap_or_default().to_string();
203 query_map.insert(key, value);
204 }
205 query_map
206 }
207
208 /// Retrieves the value of a query parameter by its key.
209 ///
210 /// # Parameters
211 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
212 ///
213 /// # Returns
214 /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
215 /// or `None` if the key does not exist.
216 pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
217 where
218 K: Into<RequestQuerysKey>,
219 {
220 self.querys
221 .get(&key.into())
222 .and_then(|data| Some(data.clone()))
223 }
224
225 /// Retrieves the value of a request header by its key.
226 ///
227 /// # Parameters
228 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
229 ///
230 /// # Returns
231 /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
232 /// or `None` if the key does not exist.
233 pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
234 where
235 K: Into<RequestHeadersKey>,
236 {
237 self.headers
238 .get(&key.into())
239 .and_then(|data| Some(data.clone()))
240 }
241
242 /// Retrieves the body content of the object as a UTF-8 encoded string.
243 ///
244 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
245 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
246 ///
247 /// # Returns
248 /// A `String` containing the body content.
249 pub fn get_body_string(&self) -> String {
250 String::from_utf8_lossy(self.get_body()).into_owned()
251 }
252
253 /// Deserializes the body content of the object into a specified type `T`.
254 ///
255 /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
256 /// It then attempts to deserialize the string into the specified type `T` using `serde_json::from_str`.
257 ///
258 /// # Type Parameters
259 /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
260 ///
261 /// # Returns
262 /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
263 /// - `Err(serde_json::Error)`: An error if the deserialization fails (e.g., invalid JSON format or type mismatch).
264 pub fn get_body_json<T>(&self) -> ResultSerdeJsonError<T>
265 where
266 T: DeserializeOwned,
267 {
268 serde_json::from_slice(self.get_body())
269 }
270
271 /// Adds a header to the request.
272 ///
273 /// This function inserts a key-value pair into the request headers.
274 /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
275 ///
276 /// # Parameters
277 /// - `key`: The header key, which will be converted into a `String`.
278 /// - `value`: The value of the header, which will be converted into a `String`.
279 ///
280 /// # Returns
281 /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
282 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
283 where
284 K: Into<String>,
285 V: Into<String>,
286 {
287 self.headers.insert(key.into(), value.into());
288 self
289 }
290
291 /// Set the body of the response.
292 ///
293 /// This method allows you to set the body of the response by converting the provided
294 /// value into a `RequestBody` type. The `body` is updated with the converted value,
295 /// and the method returns a mutable reference to the current instance for method chaining.
296 ///
297 /// # Parameters
298 /// - `body`: The body of the response to be set. It can be any type that can be converted
299 /// into a `RequestBody` using the `Into` trait.
300 ///
301 /// # Return Value
302 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
303 /// Set the body of the response.
304 ///
305 /// This method allows you to set the body of the response by converting the provided
306 /// value into a `RequestBody` type. The `body` is updated with the converted value,
307 /// and the method returns a mutable reference to the current instance for method chaining.
308 ///
309 /// # Parameters
310 /// - `body`: The body of the response to be set. It can be any type that can be converted
311 /// into a `RequestBody` using the `Into` trait.
312 ///
313 /// # Return Value
314 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
315 pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
316 self.body = body.into();
317 self
318 }
319
320 /// Set the HTTP method of the request.
321 ///
322 /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
323 /// by converting the provided value into a `RequestMethod` type. The `method` is updated
324 /// with the converted value, and the method returns a mutable reference to the current
325 /// instance for method chaining.
326 ///
327 /// # Parameters
328 /// - `method`: The HTTP method to be set for the request. It can be any type that can
329 /// be converted into a `RequestMethod` using the `Into` trait.
330 ///
331 /// # Return Value
332 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
333 pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
334 self.method = method.into();
335 self
336 }
337
338 /// Set the host of the request.
339 ///
340 /// This method allows you to set the host (e.g., www.example.com) for the request
341 /// by converting the provided value into a `RequestHost` type. The `host` is updated
342 /// with the converted value, and the method returns a mutable reference to the current
343 /// instance for method chaining.
344 ///
345 /// # Parameters
346 /// - `host`: The host to be set for the request. It can be any type that can be converted
347 /// into a `RequestHost` using the `Into` trait.
348 ///
349 /// # Return Value
350 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
351 pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
352 self.host = host.into();
353 self
354 }
355
356 /// Set the path of the request.
357 ///
358 /// This method allows you to set the path (e.g., /api/v1/resource) for the request
359 /// by converting the provided value into a `RequestPath` type. The `path` is updated
360 /// with the converted value, and the method returns a mutable reference to the current
361 /// instance for method chaining.
362 ///
363 /// # Parameters
364 /// - `path`: The path to be set for the request. It can be any type that can be converted
365 /// into a `RequestPath` using the `Into` trait.
366 ///
367 /// # Return Value
368 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
369 pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
370 self.path = path.into();
371 self
372 }
373
374 /// Sets a query parameter for the request.
375 ///
376 /// # Parameters
377 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
378 /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
379 ///
380 /// # Returns
381 /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
382 pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
383 &mut self,
384 key: K,
385 value: V,
386 ) -> &mut Self {
387 self.querys.insert(key.into(), value.into());
388 self
389 }
390
391 /// Converts the request to a formatted string representation.
392 ///
393 /// - Returns: A `String` containing formatted request details.
394 pub fn get_string(&self) -> String {
395 let body: &Vec<u8> = self.get_body();
396 format!(
397 "[Request] => [Method]: {}; [Host]: {}; [Version]: {}; [Path]: {}; [Querys]: {:?}; [Headers]: {:?}; [Body]: {};",
398 self.get_method(),
399 self.get_host(),
400 self.get_version(),
401 self.get_path(),
402 self.get_querys(),
403 self.get_headers(),
404 match std::str::from_utf8(body) {
405 Ok(string_data) => Cow::Borrowed(string_data),
406 Err(_) => Cow::Owned(format!("binary data len: {}", body.len())),
407 },
408 )
409 }
410
411 /// Retrieves the upgrade type from the request headers.
412 ///
413 /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
414 /// If the header is missing or invalid, returns the default `UpgradeType`.
415 pub fn get_upgrade_type(&self) -> UpgradeType {
416 let upgrade_type: UpgradeType = self
417 .get_header(UPGRADE)
418 .and_then(|data| data.parse::<UpgradeType>().ok())
419 .unwrap_or_default();
420 upgrade_type
421 }
422
423 /// Checks whether the WebSocket upgrade is enabled.
424 ///
425 /// - Returns: `true` if the upgrade type is WebSocket; otherwise, `false`.
426 pub fn upgrade_type_is_websocket(&self) -> bool {
427 self.get_upgrade_type().is_websocket()
428 }
429
430 /// Checks whether the upgrade type is HTTP.
431 ///
432 /// - Returns: `true` if the upgrade type is HTTP; otherwise, `false`.
433 pub fn upgrade_type_is_http(&self) -> bool {
434 self.get_upgrade_type().is_http()
435 }
436
437 /// Checks whether the upgrade type is unknown.
438 ///
439 /// - Returns: `true` if the upgrade type is unknown; otherwise, `false`.
440 pub fn upgrade_type_is_unknown(&self) -> bool {
441 self.get_upgrade_type().is_unknown()
442 }
443
444 /// Checks if the HTTP version is HTTP/1.1 or higher.
445 ///
446 /// - Returns: `true` if the HTTP version is 1.1 or higher; otherwise, `false`.
447 pub fn version_is_http1_1_or_higher(&self) -> bool {
448 self.get_version().is_http1_1_or_higher()
449 }
450
451 /// Checks whether the HTTP version is HTTP/0.9.
452 ///
453 /// - Returns: `true` if the version is HTTP/0.9; otherwise, `false`.
454 pub fn version_is_http0_9(&self) -> bool {
455 self.get_version().is_http0_9()
456 }
457
458 /// Checks whether the HTTP version is HTTP/1.0.
459 ///
460 /// - Returns: `true` if the version is HTTP/1.0; otherwise, `false`.
461 pub fn version_is_http1_0(&self) -> bool {
462 self.get_version().is_http1_0()
463 }
464
465 /// Checks whether the HTTP version is HTTP/1.1.
466 ///
467 /// - Returns: `true` if the version is HTTP/1.1; otherwise, `false`.
468 pub fn version_is_http1_1(&self) -> bool {
469 self.get_version().is_http1_1()
470 }
471
472 /// Checks whether the HTTP version is HTTP/2.
473 ///
474 /// - Returns: `true` if the version is HTTP/2; otherwise, `false`.
475 pub fn version_is_http2(&self) -> bool {
476 self.get_version().is_http2()
477 }
478
479 /// Checks whether the HTTP version is HTTP/3.
480 ///
481 /// - Returns: `true` if the version is HTTP/3; otherwise, `false`.
482 pub fn version_is_http3(&self) -> bool {
483 self.get_version().is_http3()
484 }
485
486 /// Checks whether the HTTP version is unknown.
487 ///
488 /// - Returns: `true` if the version is unknown; otherwise, `false`.
489 pub fn version_is_unknown(&self) -> bool {
490 self.get_version().is_unknown()
491 }
492
493 /// Checks whether the version belongs to the HTTP family.
494 ///
495 /// - Returns: `true` if the version is a valid HTTP version; otherwise, `false`.
496 pub fn version_is_http(&self) -> bool {
497 self.get_version().is_http()
498 }
499
500 /// Checks whether the request method is `GET`.
501 ///
502 /// - Returns: `true` if the method is `GET`; otherwise, `false`.
503 pub fn method_is_get(&self) -> bool {
504 self.get_method().is_get()
505 }
506
507 /// Checks whether the request method is `POST`.
508 ///
509 /// - Returns: `true` if the method is `POST`; otherwise, `false`.
510 pub fn method_is_post(&self) -> bool {
511 self.get_method().is_post()
512 }
513
514 /// Checks whether the request method is `PUT`.
515 ///
516 /// - Returns: `true` if the method is `PUT`; otherwise, `false`.
517 pub fn method_is_put(&self) -> bool {
518 self.get_method().is_put()
519 }
520
521 /// Checks whether the request method is `DELETE`.
522 ///
523 /// - Returns: `true` if the method is `DELETE`; otherwise, `false`.
524 pub fn method_is_delete(&self) -> bool {
525 self.get_method().is_delete()
526 }
527
528 /// Checks whether the request method is `PATCH`.
529 ///
530 /// - Returns: `true` if the method is `PATCH`; otherwise, `false`.
531 pub fn method_is_patch(&self) -> bool {
532 self.get_method().is_patch()
533 }
534
535 /// Checks whether the request method is `HEAD`.
536 ///
537 /// - Returns: `true` if the method is `HEAD`; otherwise, `false`.
538 pub fn method_is_head(&self) -> bool {
539 self.get_method().is_head()
540 }
541
542 /// Checks whether the request method is `OPTIONS`.
543 ///
544 /// - Returns: `true` if the method is `OPTIONS`; otherwise, `false`.
545 pub fn method_is_options(&self) -> bool {
546 self.get_method().is_options()
547 }
548
549 /// Checks whether the request method is `CONNECT`.
550 ///
551 /// - Returns: `true` if the method is `CONNECT`; otherwise, `false`.
552 pub fn method_is_connect(&self) -> bool {
553 self.get_method().is_connect()
554 }
555
556 /// Checks whether the request method is `TRACE`.
557 ///
558 /// - Returns: `true` if the method is `TRACE`; otherwise, `false`.
559 pub fn method_is_trace(&self) -> bool {
560 self.get_method().is_trace()
561 }
562
563 /// Checks whether the request method is `UNKNOWN`.
564 ///
565 /// - Returns: `true` if the method is `UNKNOWN`; otherwise, `false`.
566 pub fn method_is_unknown(&self) -> bool {
567 self.get_method().is_unknown()
568 }
569
570 /// Determines if keep-alive connection should be enabled for this request.
571 ///
572 /// This function checks the Connection header and HTTP version to determine if
573 /// keep-alive should be enabled. The logic is as follows:
574 ///
575 /// 1. If Connection header exists:
576 /// - Returns true if header value is "keep-alive"
577 /// - Returns false if header value is "close"
578 /// 2. If no Connection header:
579 /// - Returns true if HTTP version is 1.1 or higher
580 /// - Returns false otherwise
581 ///
582 /// # Returns
583 /// - `bool`: true if keep-alive should be enabled, false otherwise
584 pub fn is_enable_keep_alive(&self) -> bool {
585 if let Some(connection_value) = self.get_header(CONNECTION) {
586 let connection_value_lowercase: String = connection_value.to_ascii_lowercase();
587 if connection_value_lowercase == CONNECTION_KEEP_ALIVE {
588 return true;
589 } else if connection_value_lowercase == CONNECTION_CLOSE {
590 return self.upgrade_type_is_websocket();
591 }
592 }
593 self.version_is_http1_1_or_higher() || self.upgrade_type_is_websocket()
594 }
595}