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]
39 .to_string()
40 .parse::<RequestMethod>()
41 .unwrap_or_default();
42 let full_path: RequestPath = parts[1].to_string();
43 let version: RequestVersion = parts[2]
44 .to_string()
45 .parse::<RequestVersion>()
46 .unwrap_or_default();
47 let hash_index: OptionUsize = full_path.find(HASH_SYMBOL);
48 let query_index: OptionUsize = full_path.find(QUERY_SYMBOL);
49 let query_string: String = query_index.map_or(EMPTY_STR.to_owned(), |i| {
50 let temp: String = full_path[i + 1..].to_string();
51 if hash_index.is_none() || hash_index.unwrap() <= i {
52 return temp.into();
53 }
54 let data: String = temp
55 .split(HASH_SYMBOL)
56 .next()
57 .unwrap_or_default()
58 .to_string();
59 data.into()
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 = EMPTY_STR.to_owned();
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 let parts: Vec<&str> = header_line.splitn(2, COLON_SPACE_SYMBOL).collect();
78 if parts.len() != 2 {
79 continue;
80 }
81 let key: String = parts[0].trim().to_ascii_lowercase();
82 let value: String = parts[1].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.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 ) -> RequestReaderHandleResult {
118 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().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 /// - `request`: A reference to a `Request` object. This object is used as a template.
129 ///
130 /// # Returns
131 /// - `Ok`: A `Request` object populated with the HTTP request data.
132 /// - `Err`: An `RequestError` if the request is invalid or cannot be read.
133 pub async fn ws_request_from_stream(
134 stream: &ArcRwLockStream,
135 buffer_size: usize,
136 request: &mut Self,
137 ) -> RequestReaderHandleResult {
138 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
139 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
140 Self::ws_from_reader(&mut reader, buffer_size, request).await
141 }
142
143 /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
144 ///
145 /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
146 /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
147 /// based on the received data. The request body is set using the received bytes.
148 ///
149 /// # Arguments
150 /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
151 /// This reader is used to read the incoming WebSocket request data.
152 /// - `buffer_size`: - Request buffer size.
153 /// - `request` - A reference to a `Request` object. This object is used as a template.
154 ///
155 /// # Returns
156 /// - `Ok(Request)` - A `Request` object constructed from the received data.
157 /// - If no data is read (`Ok(0)`), an empty `Request` object is returned.
158 /// - If data is successfully read, the request body is set with the received bytes.
159 /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
160 pub async fn ws_from_reader(
161 reader: &mut BufReader<&mut TcpStream>,
162 buffer_size: usize,
163 request: &mut Self,
164 ) -> RequestReaderHandleResult {
165 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
166 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
167 let mut full_frame: Vec<u8> = Vec::with_capacity(buffer_size);
168 let mut error_handle = || {
169 request.body.clear();
170 };
171 loop {
172 let len: usize = match reader.read(&mut temp_buffer).await {
173 Ok(len) => len,
174 Err(err) => {
175 error_handle();
176 if err.kind() == ErrorKind::ConnectionReset
177 || err.kind() == ErrorKind::ConnectionAborted
178 {
179 return Err(RequestError::ClientDisconnected);
180 }
181 return Err(RequestError::InvalidWebSocketRequest(err.to_string()));
182 }
183 };
184 if len == 0 {
185 error_handle();
186 return Err(RequestError::IncompleteWebSocketFrame);
187 }
188 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
189 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
190 dynamic_buffer.drain(0..consumed);
191 match frame.get_opcode() {
192 WebSocketOpcode::Close => {
193 error_handle();
194 return Err(RequestError::ClientClosedConnection);
195 }
196 WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
197 continue;
198 }
199 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
200 full_frame.extend_from_slice(frame.get_payload_data());
201 if *frame.get_fin() {
202 let mut request: Request = request.clone();
203 request.body = full_frame;
204 return Ok(request);
205 }
206 }
207 _ => {
208 error_handle();
209 return Err(RequestError::InvalidWebSocketFrame(
210 "Unsupported opcode".into(),
211 ));
212 }
213 }
214 }
215 }
216 }
217
218 /// Parse querys
219 ///
220 /// # Parameters
221 /// - `query`: &str
222 ///
223 /// # Returns
224 /// - RequestQuerys
225 fn parse_querys(query: &str) -> RequestQuerys {
226 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
227 for pair in query.split(AND) {
228 let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
229 let key: String = parts.next().unwrap_or_default().to_string();
230 if key.is_empty() {
231 continue;
232 }
233 let value: String = parts.next().unwrap_or_default().to_string();
234 query_map.insert(key, value);
235 }
236 query_map
237 }
238
239 /// Retrieves the value of a query parameter by its key.
240 ///
241 /// # Parameters
242 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
243 ///
244 /// # Returns
245 /// - `OptionRequestQuerysValue`: Returns `Some(value)` if the key exists in the query parameters,
246 /// or `None` if the key does not exist.
247 pub fn get_query<K>(&self, key: K) -> OptionRequestQuerysValue
248 where
249 K: Into<RequestQuerysKey>,
250 {
251 self.querys
252 .get(&key.into())
253 .and_then(|data| Some(data.clone()))
254 }
255
256 /// Retrieves the value of a request header by its key.
257 ///
258 /// # Parameters
259 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
260 ///
261 /// # Returns
262 /// - `OptionRequestHeadersValue`: Returns `Some(value)` if the key exists in the request headers,
263 /// or `None` if the key does not exist.
264 pub fn get_header<K>(&self, key: K) -> OptionRequestHeadersValue
265 where
266 K: Into<RequestHeadersKey>,
267 {
268 self.headers
269 .get(&key.into())
270 .and_then(|data| Some(data.clone()))
271 }
272
273 /// Retrieves the body content of the object as a UTF-8 encoded string.
274 ///
275 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` into a string.
276 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character (�).
277 ///
278 /// # Returns
279 /// A `String` containing the body content.
280 pub fn get_body_string(&self) -> String {
281 String::from_utf8_lossy(self.get_body()).into_owned()
282 }
283
284 /// Deserializes the body content of the object into a specified type `T`.
285 ///
286 /// This method first retrieves the body content as a UTF-8 encoded string using `self.get_body()`.
287 /// It then attempts to deserialize the string into the specified type `T` using `json_from_slice`.
288 ///
289 /// # Type Parameters
290 /// - `T`: The target type to deserialize into. It must implement the `DeserializeOwned` trait.
291 ///
292 /// # Returns
293 /// - `Ok(T)`: The deserialized object of type `T` if the deserialization is successful.
294 /// - `Err(ResultJsonError)`: An error if the deserialization fails (e.g., invalid JSON format or type mismatch).
295 pub fn get_body_json<T>(&self) -> ResultJsonError<T>
296 where
297 T: DeserializeOwned,
298 {
299 json_from_slice(self.get_body())
300 }
301
302 /// Converts the request to a formatted string representation.
303 ///
304 /// - Returns: A `String` containing formatted request details.
305 pub fn get_string(&self) -> String {
306 let body: &Vec<u8> = self.get_body();
307 format!(
308 "[Request] => [Method]: {}; [Host]: {}; [Version]: {}; [Path]: {}; [Querys]: {:?}; [Headers]: {:?}; [Body]: {};",
309 self.get_method(),
310 self.get_host(),
311 self.get_version(),
312 self.get_path(),
313 self.get_querys(),
314 self.get_headers(),
315 match std::str::from_utf8(body) {
316 Ok(string_data) => Cow::Borrowed(string_data),
317 Err(_) => Cow::Owned(format!("binary data len: {}", body.len())),
318 },
319 )
320 }
321
322 /// Retrieves the upgrade type from the request headers.
323 ///
324 /// - Returns: The `UpgradeType` extracted from the `UPGRADE` header.
325 /// If the header is missing or invalid, returns the default `UpgradeType`.
326 pub fn get_upgrade_type(&self) -> UpgradeType {
327 let upgrade_type: UpgradeType = self
328 .get_header(UPGRADE)
329 .and_then(|data| data.parse::<UpgradeType>().ok())
330 .unwrap_or_default();
331 upgrade_type
332 }
333
334 /// Checks whether the WebSocket upgrade is enabled.
335 ///
336 /// - Returns: `true` if the upgrade type is WebSocket; otherwise, `false`.
337 pub fn is_ws(&self) -> bool {
338 self.get_upgrade_type().is_ws()
339 }
340
341 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
342 ///
343 /// - `&self` - The current instance (usually a request or context struct).
344 ///
345 /// - Returns `true` if the upgrade type is `h2c`, otherwise `false`.
346 pub fn is_h2c(&self) -> bool {
347 self.get_upgrade_type().is_h2c()
348 }
349
350 /// Checks if the current upgrade type is TLS (any version).
351 ///
352 /// - `&self` - The current instance (usually a request or context struct).
353 ///
354 /// - Returns `true` if the upgrade type is any `Tls` variant, otherwise `false`.
355 pub fn is_tls(&self) -> bool {
356 self.get_upgrade_type().is_tls()
357 }
358
359 /// Checks whether the upgrade type is unknown.
360 ///
361 /// - Returns: `true` if the upgrade type is unknown; otherwise, `false`.
362 pub fn is_unknown_upgrade(&self) -> bool {
363 self.get_upgrade_type().is_unknown()
364 }
365
366 /// Checks if the HTTP version is HTTP/1.1 or higher.
367 ///
368 /// - Returns: `true` if the HTTP version is 1.1 or higher; otherwise, `false`.
369 pub fn is_http1_1_or_higher(&self) -> bool {
370 self.get_version().is_http1_1_or_higher()
371 }
372
373 /// Checks whether the HTTP version is HTTP/0.9.
374 ///
375 /// - Returns: `true` if the version is HTTP/0.9; otherwise, `false`.
376 pub fn is_http0_9(&self) -> bool {
377 self.get_version().is_http0_9()
378 }
379
380 /// Checks whether the HTTP version is HTTP/1.0.
381 ///
382 /// - Returns: `true` if the version is HTTP/1.0; otherwise, `false`.
383 pub fn is_http1_0(&self) -> bool {
384 self.get_version().is_http1_0()
385 }
386
387 /// Checks whether the HTTP version is HTTP/1.1.
388 ///
389 /// - Returns: `true` if the version is HTTP/1.1; otherwise, `false`.
390 pub fn is_http1_1(&self) -> bool {
391 self.get_version().is_http1_1()
392 }
393
394 /// Checks whether the HTTP version is HTTP/2.
395 ///
396 /// - Returns: `true` if the version is HTTP/2; otherwise, `false`.
397 pub fn is_http2(&self) -> bool {
398 self.get_version().is_http2()
399 }
400
401 /// Checks whether the HTTP version is HTTP/3.
402 ///
403 /// - Returns: `true` if the version is HTTP/3; otherwise, `false`.
404 pub fn is_http3(&self) -> bool {
405 self.get_version().is_http3()
406 }
407
408 /// Checks whether the HTTP version is unknown.
409 ///
410 /// - Returns: `true` if the version is unknown; otherwise, `false`.
411 pub fn is_unknown_version(&self) -> bool {
412 self.get_version().is_unknown()
413 }
414
415 /// Checks whether the version belongs to the HTTP family.
416 ///
417 /// - Returns: `true` if the version is a valid HTTP version; otherwise, `false`.
418 pub fn is_http(&self) -> bool {
419 self.get_version().is_http()
420 }
421
422 /// Checks whether the request method is `GET`.
423 ///
424 /// - Returns: `true` if the method is `GET`; otherwise, `false`.
425 pub fn is_get(&self) -> bool {
426 self.get_method().is_get()
427 }
428
429 /// Checks whether the request method is `POST`.
430 ///
431 /// - Returns: `true` if the method is `POST`; otherwise, `false`.
432 pub fn is_post(&self) -> bool {
433 self.get_method().is_post()
434 }
435
436 /// Checks whether the request method is `PUT`.
437 ///
438 /// - Returns: `true` if the method is `PUT`; otherwise, `false`.
439 pub fn is_put(&self) -> bool {
440 self.get_method().is_put()
441 }
442
443 /// Checks whether the request method is `DELETE`.
444 ///
445 /// - Returns: `true` if the method is `DELETE`; otherwise, `false`.
446 pub fn is_delete(&self) -> bool {
447 self.get_method().is_delete()
448 }
449
450 /// Checks whether the request method is `PATCH`.
451 ///
452 /// - Returns: `true` if the method is `PATCH`; otherwise, `false`.
453 pub fn is_patch(&self) -> bool {
454 self.get_method().is_patch()
455 }
456
457 /// Checks whether the request method is `HEAD`.
458 ///
459 /// - Returns: `true` if the method is `HEAD`; otherwise, `false`.
460 pub fn is_head(&self) -> bool {
461 self.get_method().is_head()
462 }
463
464 /// Checks whether the request method is `OPTIONS`.
465 ///
466 /// - Returns: `true` if the method is `OPTIONS`; otherwise, `false`.
467 pub fn is_options(&self) -> bool {
468 self.get_method().is_options()
469 }
470
471 /// Checks whether the request method is `CONNECT`.
472 ///
473 /// - Returns: `true` if the method is `CONNECT`; otherwise, `false`.
474 pub fn is_connect(&self) -> bool {
475 self.get_method().is_connect()
476 }
477
478 /// Checks whether the request method is `TRACE`.
479 ///
480 /// - Returns: `true` if the method is `TRACE`; otherwise, `false`.
481 pub fn is_trace(&self) -> bool {
482 self.get_method().is_trace()
483 }
484
485 /// Checks whether the request method is `UNKNOWN`.
486 ///
487 /// - Returns: `true` if the method is `UNKNOWN`; otherwise, `false`.
488 pub fn is_unknown_method(&self) -> bool {
489 self.get_method().is_unknown()
490 }
491
492 /// Determines if keep-alive connection should be enabled for this request.
493 ///
494 /// This function checks the Connection header and HTTP version to determine if
495 /// keep-alive should be enabled. The logic is as follows:
496 ///
497 /// 1. If Connection header exists:
498 /// - Returns true if header value is "keep-alive"
499 /// - Returns false if header value is "close"
500 /// 2. If no Connection header:
501 /// - Returns true if HTTP version is 1.1 or higher
502 /// - Returns false otherwise
503 ///
504 /// # Returns
505 /// - `bool`: true if keep-alive should be enabled, false otherwise
506 pub fn is_enable_keep_alive(&self) -> bool {
507 if let Some(connection_value) = self.get_header(CONNECTION) {
508 let connection_value_lowercase: String = connection_value.to_ascii_lowercase();
509 if connection_value_lowercase == KEEP_ALIVE {
510 return true;
511 } else if connection_value_lowercase == CLOSE {
512 return self.is_ws();
513 }
514 }
515 self.is_http1_1_or_higher() || self.is_ws()
516 }
517}