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