http_type/request/impl.rs
1use crate::*;
2
3impl Default for Request {
4 fn default() -> Self {
5 Self {
6 method: Method::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 instance of `Request`.
19 ///
20 /// # Returns
21 /// - An initialized `Request` with default values.
22 pub fn new() -> Self {
23 Self::default()
24 }
25
26 /// Creates a new `Request` object from a TCP stream.
27 ///
28 /// # Parameters
29 /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`.
30 /// - `buffer_size`: Request buffer size.
31 ///
32 /// # Returns
33 /// - `Ok`: A `Request` object populated with the HTTP request data.
34 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
35 pub async fn http_from_reader(
36 reader: &mut BufReader<&mut TcpStream>,
37 buffer_size: usize,
38 ) -> RequestReaderHandleResult {
39 let mut request_line: String = String::with_capacity(buffer_size);
40 let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
41 let parts: Vec<&str> = request_line.split_whitespace().collect();
42 let parts_len: usize = parts.len();
43 if parts_len < 3 {
44 return Err(RequestError::InvalidHttpRequestPartsLength(parts_len));
45 }
46 let method: RequestMethod = parts[0].parse::<RequestMethod>().unwrap_or_default();
47 let full_path: RequestPath = parts[1].to_string();
48 let version: RequestVersion = parts[2].parse::<RequestVersion>().unwrap_or_default();
49 let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
50 let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
51 let query_string: String = query_index.map_or(String::new(), |i| {
52 let temp: &str = &full_path[i + 1..];
53 if hash_index.is_none() || hash_index.unwrap() <= i {
54 return temp.to_string();
55 }
56 temp.split(HASH_SYMBOL)
57 .next()
58 .unwrap_or_default()
59 .to_string()
60 });
61 let querys: RequestQuerys = Self::parse_querys(&query_string);
62 let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
63 full_path[..i].to_string()
64 } else {
65 full_path
66 };
67 let mut headers: RequestHeaders = hash_map_xx_hash3_64();
68 let mut host: RequestHost = String::new();
69 let mut content_length: usize = 0;
70 loop {
71 let mut header_line: String = String::with_capacity(buffer_size);
72 let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
73 let header_line: &str = header_line.trim();
74 if header_line.is_empty() {
75 break;
76 }
77 if let Some((key_part, value_part)) = header_line.split_once(COLON_SPACE_SYMBOL) {
78 let key: String = key_part.trim().to_ascii_lowercase();
79 if key.is_empty() {
80 continue;
81 }
82 let value: String = value_part.trim().to_string();
83 if key == HOST {
84 host = value.clone();
85 } else if key == CONTENT_LENGTH {
86 content_length = value.parse().unwrap_or(0);
87 }
88 headers
89 .entry(key)
90 .or_insert_with(VecDeque::new)
91 .push_back(value);
92 }
93 }
94 let mut body: RequestBody = vec![0; content_length];
95 if content_length > 0 {
96 let _ = AsyncReadExt::read_exact(reader, &mut body).await;
97 }
98 Ok(Request {
99 method,
100 host,
101 version,
102 path,
103 querys,
104 headers,
105 body,
106 })
107 }
108
109 /// Creates a new `Request` object from a TCP stream.
110 ///
111 /// # Parameters
112 /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
113 /// - `buffer_size`: Request buffer size.
114 ///
115 /// # Returns
116 /// - `Ok`: A `Request` object populated with the HTTP request data.
117 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
118 pub async fn http_from_stream(
119 stream: &ArcRwLockStream,
120 buffer_size: usize,
121 ) -> RequestReaderHandleResult {
122 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
123 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
124 Self::http_from_reader(&mut reader, buffer_size).await
125 }
126
127 /// Creates a new `Request` object from a TCP stream.
128 ///
129 /// # Parameters
130 /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
131 /// - `buffer_size`: Request buffer size.
132 /// - `request`: A reference to a `Request` object. This object is used as a template.
133 ///
134 /// # Returns
135 /// - `Ok`: A `Request` object populated with the HTTP request data.
136 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
137 pub async fn ws_from_stream(
138 stream: &ArcRwLockStream,
139 buffer_size: usize,
140 request: &mut Self,
141 ) -> RequestReaderHandleResult {
142 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
143 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
144 Self::ws_from_reader(&mut reader, buffer_size, request).await
145 }
146
147 /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
148 ///
149 /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
150 /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
151 /// based on the received data. The request body is set using the received bytes.
152 ///
153 /// # Arguments
154 /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
155 /// This reader is used to read the incoming WebSocket request data.
156 /// - `buffer_size`: - Request buffer size.
157 /// - `request` - A reference to a `Request` object. This object is used as a template.
158 ///
159 /// # Returns
160 /// - `Ok(Request)` - A `Request` object constructed from the received data.
161 /// - If no data is read (`Ok(0)`), an empty `Request` object is returned.
162 /// - If data is successfully read, the request body is set with the received bytes.
163 /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
164 pub async fn ws_from_reader(
165 reader: &mut BufReader<&mut TcpStream>,
166 buffer_size: usize,
167 request: &mut Self,
168 ) -> RequestReaderHandleResult {
169 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
170 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
171 let mut full_frame: Vec<u8> = Vec::new();
172 let mut error_handle = || {
173 request.body.clear();
174 };
175 loop {
176 let len: usize = match reader.read(&mut temp_buffer).await {
177 Ok(len) => len,
178 Err(err) => {
179 error_handle();
180 if err.kind() == ErrorKind::ConnectionReset
181 || err.kind() == ErrorKind::ConnectionAborted
182 {
183 return Err(RequestError::ClientDisconnected);
184 }
185 return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
186 }
187 };
188 if len == 0 {
189 error_handle();
190 return Err(RequestError::IncompleteWebSocketFrame);
191 }
192 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
193 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
194 dynamic_buffer.drain(0..consumed);
195 match frame.get_opcode() {
196 WebSocketOpcode::Close => {
197 error_handle();
198 return Err(RequestError::ClientClosedConnection);
199 }
200 WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
201 continue;
202 }
203 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
204 full_frame.extend_from_slice(frame.get_payload_data());
205 if *frame.get_fin() {
206 let mut request: Request = request.clone();
207 request.body = full_frame;
208 return Ok(request);
209 }
210 }
211 _ => {
212 error_handle();
213 return Err(RequestError::InvalidWebSocketFrame(
214 "Unsupported opcode".into(),
215 ));
216 }
217 }
218 }
219 }
220 }
221
222 /// Parse querys
223 ///
224 /// # Parameters
225 /// - `query`: &str
226 ///
227 /// # Returns
228 /// - RequestQuerys
229 fn parse_querys(query: &str) -> RequestQuerys {
230 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
231 for pair in query.split(AND) {
232 if let Some((key, value)) = pair.split_once(EQUAL) {
233 if !key.is_empty() {
234 query_map.insert(key.to_string(), value.to_string());
235 }
236 } else if !pair.is_empty() {
237 query_map.insert(pair.to_string(), String::new());
238 }
239 }
240 query_map
241 }
242
243 /// Retrieves the value of a query parameter by its key.
244 ///
245 /// # Parameters
246 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
247 ///
248 /// # Returns
249 /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
250 /// or `None` if the key does not exist.
251 pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
252 where
253 K: Into<RequestQuerysKey>,
254 {
255 self.querys.get(&key.into()).cloned()
256 }
257
258 /// Retrieves the value of a request header by its key.
259 ///
260 /// # Parameters
261 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
262 ///
263 /// # Returns
264 /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
265 /// or `None` if the key does not exist.
266 pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
267 where
268 K: Into<RequestHeadersKey>,
269 {
270 self.headers.get(&key.into()).cloned()
271 }
272
273 /// Retrieves the first value of a request header by its key.
274 ///
275 /// # Parameters
276 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
277 ///
278 /// # Returns
279 /// - `OptionRequestHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
280 /// or `None` if the key does not exist or has no values.
281 pub fn get_header_front<K>(&self, key: K) -> OptionRequestHeadersValueItem
282 where
283 K: Into<RequestHeadersKey>,
284 {
285 self.headers
286 .get(&key.into())
287 .and_then(|values| values.front().cloned())
288 }
289
290 /// Retrieves the last value of a request header by its key.
291 ///
292 /// # Parameters
293 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
294 ///
295 /// # Returns
296 /// - `OptionRequestHeadersValueItem`: Returns `Some(value)` if the key exists and has at least one value,
297 /// or `None` if the key does not exist or has no values.
298 pub fn get_header_back<K>(&self, key: K) -> OptionRequestHeadersValueItem
299 where
300 K: Into<RequestHeadersKey>,
301 {
302 self.headers
303 .get(&key.into())
304 .and_then(|values| values.back().cloned())
305 }
306
307 /// Retrieves the number of values for a specific header.
308 ///
309 /// # Parameters
310 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
311 ///
312 /// # Returns
313 /// - `usize`: The number of values for the specified header. Returns 0 if the header does not exist.
314 pub fn get_header_len<K>(&self, key: K) -> usize
315 where
316 K: Into<RequestHeadersKey>,
317 {
318 self.headers
319 .get(&key.into())
320 .map(|values| values.len())
321 .unwrap_or(0)
322 }
323
324 /// Retrieves the total number of header values across all headers.
325 ///
326 /// # Returns
327 /// - `usize`: The total count of all header values.
328 pub fn get_headers_values_length(&self) -> usize {
329 self.headers.values().map(|values| values.len()).sum()
330 }
331
332 /// Retrieves the number of unique headers.
333 ///
334 /// # Returns
335 /// - `usize`: The number of unique header keys.
336 pub fn get_headers_length(&self) -> usize {
337 self.headers.len()
338 }
339
340 /// Checks if a specific header exists.
341 ///
342 /// # Parameters
343 /// - `key`: The header key to check, which will be converted into a `RequestHeadersKey`.
344 ///
345 /// # Returns
346 /// - `bool`: Returns `true` if the header exists, `false` otherwise.
347 pub fn has_header<K>(&self, key: K) -> bool
348 where
349 K: Into<RequestHeadersKey>,
350 {
351 self.headers.contains_key(&key.into())
352 }
353
354 /// Checks if a header contains a specific value.
355 ///
356 /// # Parameters
357 /// - `key`: The header key to check, which will be converted into a `RequestHeadersKey`.
358 /// - `value`: The value to search for in the header.
359 ///
360 /// # Returns
361 /// - `bool`: Returns `true` if the header exists and contains the specified value, `false` otherwise.
362 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
363 where
364 K: Into<RequestHeadersKey>,
365 V: Into<RequestHeadersValueItem>,
366 {
367 let key: RequestHeadersKey = key.into();
368 let value: RequestHeadersValueItem = value.into();
369 if let Some(values) = self.headers.get(&key) {
370 values.contains(&value)
371 } else {
372 false
373 }
374 }
375
376 /// Retrieves the body content of the object as a UTF-8 encoded string.
377 ///
378 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
379 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
380 ///
381 /// # Returns
382 /// A `String` containing the body content.
383 pub fn get_body_string(&self) -> String {
384 String::from_utf8_lossy(self.get_body()).into_owned()
385 }
386
387 /// Deserializes the body content of the object into a specified type `T`.
388 ///
389 /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
390 /// It then attempts to deserialize the string into the specified type `T` using `json_from_slice`.
391 ///
392 /// # Type Parameters
393 /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
394 ///
395 /// # Returns
396 /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
397 /// - `Err(ResultJsonError)`: An error if the deserialization fails.
398 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
399 where
400 T: DeserializeOwned,
401 {
402 json_from_slice(self.get_body())
403 }
404
405 /// Converts the request to a formatted string representation.
406 ///
407 /// - Returns: A `String` containing formatted request details.
408 pub fn get_string(&self) -> String {
409 let body: &Vec<u8> = self.get_body();
410 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
411 PLAIN
412 } else {
413 BINARY
414 };
415 format!(
416 "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
417 self.get_method(),
418 self.get_host(),
419 self.get_version(),
420 self.get_path(),
421 self.get_querys(),
422 self.get_headers(),
423 body.len(),
424 body_type
425 )
426 }
427
428 /// Retrieves the upgrade type from the request headers.
429 ///
430 /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
431 /// If the header is missing or invalid, returns the default `UpgradeType`.
432 pub fn get_upgrade_type(&self) -> UpgradeType {
433 let upgrade_type: UpgradeType = self
434 .get_header_back(UPGRADE)
435 .and_then(|data| data.parse::<UpgradeType>().ok())
436 .unwrap_or_default();
437 upgrade_type
438 }
439
440 /// Checks whether the WebSocket upgrade is enabled.
441 ///
442 /// - Returns: `true` if the upgrade type is WebSocket; otherwise, `false`.
443 pub fn is_ws(&self) -> bool {
444 self.get_upgrade_type().is_ws()
445 }
446
447 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
448 ///
449 /// - `&self` - The current instance (usually a request or context struct).
450 ///
451 /// - Returns `true` if the upgrade type is `h2c`, otherwise `false`.
452 pub fn is_h2c(&self) -> bool {
453 self.get_upgrade_type().is_h2c()
454 }
455
456 /// Checks if the current upgrade type is TLS (any version).
457 ///
458 /// - `&self` - The current instance (usually a request or context struct).
459 ///
460 /// - Returns `true` if the upgrade type is any `Tls` variant, otherwise `false`.
461 pub fn is_tls(&self) -> bool {
462 self.get_upgrade_type().is_tls()
463 }
464
465 /// Checks whether the upgrade type is unknown.
466 ///
467 /// - Returns: `true` if the upgrade type is unknown; otherwise, `false`.
468 pub fn is_unknown_upgrade(&self) -> bool {
469 self.get_upgrade_type().is_unknown()
470 }
471
472 /// Checks if the HTTP version is HTTP/1.1 or higher.
473 ///
474 /// - Returns: `true` if the HTTP version is 1.1 or higher; otherwise, `false`.
475 pub fn is_http1_1_or_higher(&self) -> bool {
476 self.get_version().is_http1_1_or_higher()
477 }
478
479 /// Checks whether the HTTP version is HTTP/0.9.
480 ///
481 /// - Returns: `true` if the version is HTTP/0.9; otherwise, `false`.
482 pub fn is_http0_9(&self) -> bool {
483 self.get_version().is_http0_9()
484 }
485
486 /// Checks whether the HTTP version is HTTP/1.0.
487 ///
488 /// - Returns: `true` if the version is HTTP/1.0; otherwise, `false`.
489 pub fn is_http1_0(&self) -> bool {
490 self.get_version().is_http1_0()
491 }
492
493 /// Checks whether the HTTP version is HTTP/1.1.
494 ///
495 /// - Returns: `true` if the version is HTTP/1.1; otherwise, `false`.
496 pub fn is_http1_1(&self) -> bool {
497 self.get_version().is_http1_1()
498 }
499
500 /// Checks whether the HTTP version is HTTP/2.
501 ///
502 /// - Returns: `true` if the version is HTTP/2; otherwise, `false`.
503 pub fn is_http2(&self) -> bool {
504 self.get_version().is_http2()
505 }
506
507 /// Checks whether the HTTP version is HTTP/3.
508 ///
509 /// - Returns: `true` if the version is HTTP/3; otherwise, `false`.
510 pub fn is_http3(&self) -> bool {
511 self.get_version().is_http3()
512 }
513
514 /// Checks whether the HTTP version is unknown.
515 ///
516 /// - Returns: `true` if the version is unknown; otherwise, `false`.
517 pub fn is_unknown_version(&self) -> bool {
518 self.get_version().is_unknown()
519 }
520
521 /// Checks whether the version belongs to the HTTP family.
522 ///
523 /// - Returns: `true` if the version is a valid HTTP version; otherwise, `false`.
524 pub fn is_http(&self) -> bool {
525 self.get_version().is_http()
526 }
527
528 /// Checks whether the request method is `GET`.
529 ///
530 /// - Returns: `true` if the method is `GET`; otherwise, `false`.
531 pub fn is_get(&self) -> bool {
532 self.get_method().is_get()
533 }
534
535 /// Checks whether the request method is `POST`.
536 ///
537 /// - Returns: `true` if the method is `POST`; otherwise, `false`.
538 pub fn is_post(&self) -> bool {
539 self.get_method().is_post()
540 }
541
542 /// Checks whether the request method is `PUT`.
543 ///
544 /// - Returns: `true` if the method is `PUT`; otherwise, `false`.
545 pub fn is_put(&self) -> bool {
546 self.get_method().is_put()
547 }
548
549 /// Checks whether the request method is `DELETE`.
550 ///
551 /// - Returns: `true` if the method is `DELETE`; otherwise, `false`.
552 pub fn is_delete(&self) -> bool {
553 self.get_method().is_delete()
554 }
555
556 /// Checks whether the request method is `PATCH`.
557 ///
558 /// - Returns: `true` if the method is `PATCH`; otherwise, `false`.
559 pub fn is_patch(&self) -> bool {
560 self.get_method().is_patch()
561 }
562
563 /// Checks whether the request method is `HEAD`.
564 ///
565 /// - Returns: `true` if the method is `HEAD`; otherwise, `false`.
566 pub fn is_head(&self) -> bool {
567 self.get_method().is_head()
568 }
569
570 /// Checks whether the request method is `OPTIONS`.
571 ///
572 /// - Returns: `true` if the method is `OPTIONS`; otherwise, `false`.
573 pub fn is_options(&self) -> bool {
574 self.get_method().is_options()
575 }
576
577 /// Checks whether the request method is `CONNECT`.
578 ///
579 /// - Returns: `true` if the method is `CONNECT`; otherwise, `false`.
580 pub fn is_connect(&self) -> bool {
581 self.get_method().is_connect()
582 }
583
584 /// Checks whether the request method is `TRACE`.
585 ///
586 /// - Returns: `true` if the method is `TRACE`; otherwise, `false`.
587 pub fn is_trace(&self) -> bool {
588 self.get_method().is_trace()
589 }
590
591 /// Checks whether the request method is `UNKNOWN`.
592 ///
593 /// - Returns: `true` if the method is `UNKNOWN`; otherwise, `false`.
594 pub fn is_unknown_method(&self) -> bool {
595 self.get_method().is_unknown()
596 }
597
598 /// Determines if keep-alive connection should be enabled for this request.
599 ///
600 /// This function checks the Connection header and HTTP version to determine if
601 /// keep-alive should be enabled. The logic is as follows:
602 ///
603 /// 1. If Connection header exists:
604 /// - Returns true if header value is "keep-alive"
605 /// - Returns false if header value is "close"
606 /// 2. If no Connection header:
607 /// - Returns true if HTTP version is 1.1 or higher
608 /// - Returns false otherwise
609 ///
610 /// # Returns
611 /// - `bool`: true if keep-alive should be enabled, false otherwise
612 pub fn is_enable_keep_alive(&self) -> bool {
613 if let Some(connection_value) = self.get_header_back(CONNECTION) {
614 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
615 return true;
616 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
617 return self.is_ws();
618 }
619 }
620 self.is_http1_1_or_higher() || self.is_ws()
621 }
622}