http_type/request/impl.rs
1use crate::*;
2
3/// Implements the `std::error::Error` trait for `RequestError`.
4impl std::error::Error for RequestError {}
5
6/// Provides a default value for `RequestError`.
7impl Default for RequestError {
8 /// Provides a default value for `RequestError`.
9 ///
10 /// Returns a `RequestError::Unknown` with `HttpStatus::InternalServerError`.
11 fn default() -> Self {
12 RequestError::Unknown(HttpStatus::InternalServerError)
13 }
14}
15
16impl RequestError {
17 /// Gets the HTTP status associated with this error.
18 ///
19 /// Returns the HttpStatus enum variant that corresponds to this error.
20 ///
21 /// # Arguments
22 ///
23 /// - `&self` - The RequestError instance.
24 ///
25 /// # Returns
26 ///
27 /// - `HttpStatus` - The HTTP status associated with this error.
28 #[inline(always)]
29 pub fn get_http_status(&self) -> HttpStatus {
30 match self {
31 Self::HttpRead(status) => *status,
32 Self::GetTcpStream(status) => *status,
33 Self::GetTlsStream(status) => *status,
34 Self::ReadConnection(status) => *status,
35 Self::RequestAborted(status) => *status,
36 Self::TlsStreamConnect(status) => *status,
37 Self::NeedOpenRedirect(status) => *status,
38 Self::MaxRedirectTimes(status) => *status,
39 Self::MethodsNotSupport(status) => *status,
40 Self::RedirectInvalidUrl(status) => *status,
41 Self::ClientDisconnected(status) => *status,
42 Self::RedirectUrlDeadLoop(status) => *status,
43 Self::ClientClosedConnection(status) => *status,
44 Self::IncompleteWebSocketFrame(status) => *status,
45 Self::RequestTooLong(status) => *status,
46 Self::PathTooLong(status) => *status,
47 Self::QueryTooLong(status) => *status,
48 Self::HeaderLineTooLong(status) => *status,
49 Self::TooManyHeaders(status) => *status,
50 Self::HeaderKeyTooLong(status) => *status,
51 Self::HeaderValueTooLong(status) => *status,
52 Self::ContentLengthTooLarge(status) => *status,
53 Self::InvalidContentLength(status) => *status,
54 Self::InvalidUrlScheme(status) => *status,
55 Self::InvalidUrlHost(status) => *status,
56 Self::InvalidUrlPort(status) => *status,
57 Self::InvalidUrlPath(status) => *status,
58 Self::InvalidUrlQuery(status) => *status,
59 Self::InvalidUrlFragment(status) => *status,
60 Self::ReadTimeout(status) => *status,
61 Self::WriteTimeout(status) => *status,
62 Self::TcpConnectionFailed(status) => *status,
63 Self::TlsHandshakeFailed(status) => *status,
64 Self::TlsCertificateInvalid(status) => *status,
65 Self::WebSocketFrameTooLarge(status) => *status,
66 Self::WebSocketOpcodeUnsupported(status) => *status,
67 Self::WebSocketMaskMissing(status) => *status,
68 Self::WebSocketPayloadCorrupted(status) => *status,
69 Self::WebSocketInvalidUtf8(status) => *status,
70 Self::WebSocketInvalidCloseCode(status) => *status,
71 Self::WebSocketInvalidExtension(status) => *status,
72 Self::HttpRequestPartsInsufficient(status) => *status,
73 Self::TcpStreamConnect(status) => *status,
74 Self::TlsConnectorBuild(status) => *status,
75 Self::InvalidUrl(status) => *status,
76 Self::ConfigReadError(status) => *status,
77 Self::TcpStreamConnectString(status) => *status,
78 Self::TlsConnectorBuildString(status) => *status,
79 Self::Request(_) => HttpStatus::BadRequest,
80 Self::Unknown(status) => *status,
81 }
82 }
83
84 /// Gets the numeric HTTP status code associated with this error.
85 ///
86 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
87 ///
88 /// # Arguments
89 ///
90 /// - `&self` - The RequestError instance.
91 ///
92 /// # Returns
93 ///
94 /// - `ResponseStatusCode` - The numeric HTTP status code.
95 pub fn get_http_status_code(&self) -> ResponseStatusCode {
96 self.get_http_status().code()
97 }
98}
99
100impl Default for RequestConfig {
101 /// Creates a `RequestConfig` with secure default values.
102 ///
103 /// # Returns
104 ///
105 /// - `RequestConfig` - A new config instance with secure defaults.
106 #[inline(always)]
107 fn default() -> Self {
108 Self {
109 buffer_size: DEFAULT_BUFFER_SIZE,
110 max_request_line_length: DEFAULT_MAX_REQUEST_LINE_LENGTH,
111 max_path_length: DEFAULT_MAX_PATH_LENGTH,
112 max_query_length: DEFAULT_MAX_QUERY_LENGTH,
113 max_header_line_length: DEFAULT_MAX_HEADER_LINE_LENGTH,
114 max_header_count: DEFAULT_MAX_HEADER_COUNT,
115 max_header_key_length: DEFAULT_MAX_HEADER_KEY_LENGTH,
116 max_header_value_length: DEFAULT_MAX_HEADER_VALUE_LENGTH,
117 max_body_size: DEFAULT_MAX_BODY_SIZE,
118 max_ws_frame_size: DEFAULT_MAX_WS_FRAME_SIZE,
119 max_ws_frames: DEFAULT_MAX_WS_FRAMES,
120 http_read_timeout_ms: DEFAULT_HTTP_READ_TIMEOUT_MS,
121 ws_read_timeout_ms: DEFAULT_WS_READ_TIMEOUT_MS,
122 }
123 }
124}
125
126impl RequestConfig {
127 /// Creates a config optimized for high-security environments.
128 ///
129 /// This configuration uses more restrictive limits to provide
130 /// maximum protection against various attacks.
131 ///
132 /// # Returns
133 ///
134 /// - `RequestConfig` - A new config with high-security settings.
135 #[inline(always)]
136 pub fn high_security() -> Self {
137 Self {
138 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
139 max_request_line_length: DEFAULT_HIGH_SECURITY_MAX_REQUEST_LINE_LENGTH,
140 max_path_length: DEFAULT_HIGH_SECURITY_MAX_PATH_LENGTH,
141 max_query_length: DEFAULT_HIGH_SECURITY_MAX_QUERY_LENGTH,
142 max_header_line_length: DEFAULT_HIGH_SECURITY_MAX_HEADER_LINE_LENGTH,
143 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
144 max_header_key_length: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_LENGTH,
145 max_header_value_length: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_LENGTH,
146 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
147 max_ws_frame_size: DEFAULT_HIGH_SECURITY_MAX_WS_FRAME_SIZE,
148 max_ws_frames: DEFAULT_HIGH_SECURITY_MAX_WS_FRAMES,
149 http_read_timeout_ms: DEFAULT_HIGH_SECURITY_HTTP_READ_TIMEOUT_MS,
150 ws_read_timeout_ms: DEFAULT_HIGH_SECURITY_WS_READ_TIMEOUT_MS,
151 }
152 }
153}
154
155/// Provides a default value for `Request`.
156///
157/// Returns a new `Request` instance with all fields initialized to their default values.
158impl Default for Request {
159 #[inline(always)]
160 fn default() -> Self {
161 Self {
162 method: Method::default(),
163 host: String::new(),
164 version: HttpVersion::default(),
165 path: String::new(),
166 querys: hash_map_xx_hash3_64(),
167 headers: hash_map_xx_hash3_64(),
168 body: Vec::new(),
169 }
170 }
171}
172
173impl Request {
174 /// Parses a query string as_ref key-value pairs.
175 ///
176 /// Expects format "key1=value1&key2=value2". Empty values are allowed.
177 ///
178 /// # Arguments
179 ///
180 /// - `&str` - The query string to parse.
181 ///
182 /// # Returns
183 ///
184 /// - `HashMap<String, String>` - The parsed query parameters.
185 fn parse_querys<Q>(query: Q) -> RequestQuerys
186 where
187 Q: AsRef<str>,
188 {
189 let mut query_map: RequestQuerys = hash_map_xx_hash3_64();
190 for pair in query.as_ref().split(AND) {
191 if let Some((key, value)) = pair.split_once(EQUAL) {
192 if !key.is_empty() {
193 query_map.insert(key.to_string(), value.to_string());
194 }
195 } else if !pair.is_empty() {
196 query_map.insert(pair.to_string(), String::new());
197 }
198 }
199 query_map
200 }
201
202 /// Parses HTTP headers from a buffered reader.
203 ///
204 /// This method reads header lines from the provided buffered reader until an empty line
205 /// is encountered, which indicates the end of headers. It validates header count, length,
206 /// and content according to the provided configuration.
207 ///
208 /// # Arguments
209 ///
210 /// - `&mut R` - A mutable reference to a buffered reader implementing `AsyncBufReadExt`.
211 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
212 ///
213 /// # Returns
214 ///
215 /// - `Result<(RequestHeaders, RequestHost, usize), RequestError>` - A tuple containing:
216 /// - The parsed headers as a hash map
217 /// - The host value extracted from the Host header
218 /// - The content length extracted from the Content-Length header
219 /// - Or an error if parsing fails
220 async fn parse_headers<R>(
221 reader: &mut R,
222 config: &RequestConfig,
223 ) -> Result<(RequestHeaders, RequestHost, usize), RequestError>
224 where
225 R: AsyncBufReadExt + Unpin,
226 {
227 let buffer_size: usize = *config.get_buffer_size();
228 let mut headers: RequestHeaders = hash_map_xx_hash3_64();
229 let mut host: RequestHost = String::new();
230 let mut content_length: usize = 0;
231 let mut header_count: usize = 0;
232 loop {
233 let header_line: &mut String = &mut String::with_capacity(buffer_size);
234 let bytes_read: usize = AsyncBufReadExt::read_line(reader, header_line)
235 .await
236 .map_err(|_| RequestError::HttpRead(HttpStatus::BadRequest))?;
237 if bytes_read > config.max_header_line_length {
238 return Err(RequestError::HeaderLineTooLong(
239 HttpStatus::RequestHeaderFieldsTooLarge,
240 ));
241 }
242 let header_line: &str = header_line.trim();
243 if header_line.is_empty() {
244 break;
245 }
246 header_count += 1;
247 if header_count > config.max_header_count {
248 return Err(RequestError::TooManyHeaders(
249 HttpStatus::RequestHeaderFieldsTooLarge,
250 ));
251 }
252 if let Some((key_part, value_part)) = header_line.split_once(COLON) {
253 let key: String = key_part.trim().to_ascii_lowercase();
254 if key.is_empty() {
255 continue;
256 }
257 if key.len() > config.max_header_key_length {
258 return Err(RequestError::HeaderKeyTooLong(
259 HttpStatus::RequestHeaderFieldsTooLarge,
260 ));
261 }
262 let value: String = value_part.trim().to_string();
263 if value.len() > config.max_header_value_length {
264 return Err(RequestError::HeaderValueTooLong(
265 HttpStatus::RequestHeaderFieldsTooLarge,
266 ));
267 }
268 if key == HOST {
269 host = value.clone();
270 } else if key == CONTENT_LENGTH {
271 match value.parse::<usize>() {
272 Ok(length) => {
273 if length > config.max_body_size {
274 return Err(RequestError::ContentLengthTooLarge(
275 HttpStatus::PayloadTooLarge,
276 ));
277 }
278 content_length = length;
279 }
280 Err(_) => {
281 return Err(RequestError::InvalidContentLength(HttpStatus::BadRequest));
282 }
283 }
284 }
285 headers.entry(key).or_default().push_back(value);
286 }
287 }
288 Ok((headers, host, content_length))
289 }
290
291 /// Parses an HTTP request from a TCP stream.
292 ///
293 /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
294 ///
295 /// # Arguments
296 ///
297 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
298 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
299 ///
300 /// # Returns
301 ///
302 /// - `Result<Request, RequestError>` - The parsed request or an error.
303 pub async fn http_from_stream(
304 stream: &ArcRwLockStream,
305 config: &RequestConfig,
306 ) -> Result<Request, RequestError> {
307 timeout(
308 Duration::from_millis(config.http_read_timeout_ms),
309 async move {
310 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
311 let buffer_size: usize = *config.get_buffer_size();
312 let reader: &mut BufReader<&mut TcpStream> =
313 &mut BufReader::with_capacity(buffer_size, &mut buf_stream);
314 let mut request_line: String = String::with_capacity(buffer_size);
315 let bytes_read: usize = AsyncBufReadExt::read_line(reader, &mut request_line)
316 .await
317 .map_err(|_| RequestError::HttpRead(HttpStatus::BadRequest))?;
318 if bytes_read > config.max_request_line_length {
319 return Err(RequestError::RequestTooLong(HttpStatus::BadRequest));
320 }
321 let parts: Vec<&str> = request_line.split_whitespace().collect();
322 let parts_len: usize = parts.len();
323 if parts_len < 3 {
324 return Err(RequestError::HttpRequestPartsInsufficient(
325 HttpStatus::BadRequest,
326 ));
327 }
328 let method: RequestMethod = parts[0]
329 .parse::<RequestMethod>()
330 .unwrap_or(Method::Unknown(parts[0].to_string()));
331 let full_path: &str = parts[1];
332 if full_path.len() > config.max_path_length {
333 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
334 }
335 let full_path: RequestPath = full_path.to_string();
336 let version: RequestVersion = parts[2]
337 .parse::<RequestVersion>()
338 .unwrap_or(RequestVersion::Unknown(parts[2].to_string()));
339 let hash_index: Option<usize> = full_path.find(HASH);
340 let query_index: Option<usize> = full_path.find(QUERY);
341 let query_string: String = query_index.map_or_else(String::new, |i| {
342 let temp: &str = &full_path[i + 1..];
343 if hash_index.is_none() || hash_index.unwrap() <= i {
344 return temp.to_owned();
345 }
346 temp.split(HASH).next().unwrap_or_default().to_owned()
347 });
348 if query_string.len() > config.max_query_length {
349 return Err(RequestError::QueryTooLong(HttpStatus::URITooLong));
350 }
351 let querys: RequestQuerys = Self::parse_querys(&query_string);
352 let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
353 full_path[..i].to_owned()
354 } else {
355 full_path.to_owned()
356 };
357 let (headers, host, content_length): (RequestHeaders, RequestHost, usize) =
358 Self::parse_headers(reader, config).await?;
359 let mut body: RequestBody = Vec::with_capacity(content_length);
360 if content_length > 0 {
361 body.resize(content_length, 0);
362 AsyncReadExt::read_exact(reader, &mut body)
363 .await
364 .map_err(|_| RequestError::ReadConnection(HttpStatus::BadRequest))?;
365 }
366 Ok(Request {
367 method,
368 host,
369 version,
370 path,
371 querys,
372 headers,
373 body,
374 })
375 },
376 )
377 .await
378 .map_err(|_| RequestError::ReadTimeout(HttpStatus::RequestTimeout))?
379 }
380
381 /// Parses a WebSocket request from a TCP stream.
382 ///
383 /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
384 ///
385 /// # Arguments
386 ///
387 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
388 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
389 ///
390 /// # Returns
391 ///
392 /// - `Result<Request, RequestError>` - The parsed WebSocket request or an error.
393 pub async fn ws_from_stream(
394 &mut self,
395 stream: &ArcRwLockStream,
396 config: &RequestConfig,
397 ) -> Result<Request, RequestError> {
398 let buffer_size: usize = *config.get_buffer_size();
399 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
400 let temp_buffer_size: usize = buffer_size;
401 let mut temp_buffer: Vec<u8> = vec![0; temp_buffer_size];
402 let mut full_frame: Vec<u8> = Vec::with_capacity(config.max_ws_frame_size);
403 let mut frame_count: usize = 0;
404 let mut is_client_response: bool = false;
405 let ws_read_timeout_ms: u64 =
406 (config.ws_read_timeout_ms >> 1) + (config.ws_read_timeout_ms & 1);
407 let timeout_duration: Duration = Duration::from_millis(ws_read_timeout_ms);
408 loop {
409 let len: usize = match timeout(
410 timeout_duration,
411 stream.write().await.read(&mut temp_buffer),
412 )
413 .await
414 {
415 Ok(result) => match result {
416 Ok(len) => len,
417 Err(error) => {
418 if error.kind() == ErrorKind::ConnectionReset
419 || error.kind() == ErrorKind::ConnectionAborted
420 {
421 return Err(RequestError::ClientDisconnected(HttpStatus::BadRequest));
422 }
423 return Err(RequestError::Unknown(HttpStatus::InternalServerError));
424 }
425 },
426 Err(_) => {
427 if !is_client_response {
428 return Err(RequestError::ReadTimeout(HttpStatus::RequestTimeout));
429 }
430 is_client_response = false;
431 stream
432 .try_send_body(&PING_FRAME)
433 .await
434 .map_err(|_| RequestError::WriteTimeout(HttpStatus::InternalServerError))?;
435 let _ = stream.try_flush().await;
436 continue;
437 }
438 };
439 if len == 0 {
440 return Err(RequestError::IncompleteWebSocketFrame(
441 HttpStatus::BadRequest,
442 ));
443 }
444 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
445 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
446 is_client_response = true;
447 dynamic_buffer.drain(0..consumed);
448 frame_count += 1;
449 if frame_count > config.max_ws_frames {
450 return Err(RequestError::TooManyHeaders(
451 HttpStatus::RequestHeaderFieldsTooLarge,
452 ));
453 }
454 match frame.get_opcode() {
455 WebSocketOpcode::Close => {
456 return Err(RequestError::ClientClosedConnection(HttpStatus::BadRequest));
457 }
458 WebSocketOpcode::Ping | WebSocketOpcode::Pong => {
459 continue;
460 }
461 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
462 let payload_data: &[u8] = frame.get_payload_data();
463 if payload_data.len() > config.max_ws_frame_size {
464 return Err(RequestError::WebSocketFrameTooLarge(
465 HttpStatus::PayloadTooLarge,
466 ));
467 }
468 if full_frame.len() + payload_data.len() > config.max_ws_frame_size {
469 return Err(RequestError::WebSocketFrameTooLarge(
470 HttpStatus::PayloadTooLarge,
471 ));
472 }
473 full_frame.extend_from_slice(payload_data);
474 if *frame.get_fin() {
475 let mut request: Request = self.clone();
476 request.body = full_frame;
477 return Ok(request);
478 }
479 }
480 _ => {
481 return Err(RequestError::WebSocketOpcodeUnsupported(
482 HttpStatus::NotImplemented,
483 ));
484 }
485 }
486 }
487 }
488 }
489
490 /// Tries to get a query parameter value by key.
491 ///
492 /// The key type must implement AsRef<str> conversion.
493 ///
494 /// # Arguments
495 ///
496 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
497 ///
498 /// # Returns
499 ///
500 /// - `Option<RequestQuerysValue>` - The parameter value if exists.
501 #[inline(always)]
502 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
503 where
504 K: AsRef<str>,
505 {
506 self.querys.get(key.as_ref()).cloned()
507 }
508
509 /// Gets a query parameter value by key.
510 ///
511 /// The key type must implement AsRef<str> conversion.
512 ///
513 /// # Arguments
514 ///
515 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
516 ///
517 /// # Returns
518 ///
519 /// - `RequestQuerysValue` - The parameter value if exists.
520 ///
521 /// # Panics
522 ///
523 /// This function will panic if the query parameter key is not found.
524 #[inline(always)]
525 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
526 where
527 K: AsRef<str>,
528 {
529 self.try_get_query(key).unwrap()
530 }
531
532 /// Tries to retrieve the value of a request header by its key.
533 ///
534 /// # Arguments
535 ///
536 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
537 ///
538 /// # Returns
539 ///
540 /// - `Option<RequestHeadersValue>` - The optional header values.
541 #[inline(always)]
542 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
543 where
544 K: AsRef<str>,
545 {
546 self.headers.get(key.as_ref()).cloned()
547 }
548
549 /// Retrieves the value of a request header by its key.
550 ///
551 /// # Arguments
552 ///
553 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
554 ///
555 /// # Returns
556 ///
557 /// - `RequestHeadersValue` - The optional header values.
558 ///
559 /// # Panics
560 ///
561 /// This function will panic if the header key is not found.
562 #[inline(always)]
563 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
564 where
565 K: AsRef<str>,
566 {
567 self.try_get_header(key).unwrap()
568 }
569
570 /// Tries to retrieve the first value of a request header by its key.
571 ///
572 /// # Arguments
573 ///
574 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
575 ///
576 /// # Returns
577 ///
578 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
579 #[inline(always)]
580 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
581 where
582 K: AsRef<str>,
583 {
584 self.headers
585 .get(key.as_ref())
586 .and_then(|values| values.front().cloned())
587 }
588
589 /// Retrieves the first value of a request header by its key.
590 ///
591 /// # Arguments
592 ///
593 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
594 ///
595 /// # Returns
596 ///
597 /// - `RequestHeadersValueItem` - The first header value if exists.
598 ///
599 /// # Panics
600 ///
601 /// This function will panic if the header key is not found.
602 #[inline(always)]
603 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
604 where
605 K: AsRef<str>,
606 {
607 self.try_get_header_front(key).unwrap()
608 }
609
610 /// Tries to retrieve the last value of a request header by its key.
611 ///
612 /// # Arguments
613 ///
614 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
615 ///
616 /// # Returns
617 ///
618 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
619 #[inline(always)]
620 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
621 where
622 K: AsRef<str>,
623 {
624 self.headers
625 .get(key.as_ref())
626 .and_then(|values| values.back().cloned())
627 }
628
629 /// Retrieves the last value of a request header by its key.
630 ///
631 /// # Arguments
632 ///
633 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
634 ///
635 /// # Returns
636 ///
637 /// - `RequestHeadersValueItem` - The last header value if exists.
638 ///
639 /// # Panics
640 ///
641 /// This function will panic if the header key is not found.
642 #[inline(always)]
643 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
644 where
645 K: AsRef<str>,
646 {
647 self.try_get_header_back(key).unwrap()
648 }
649
650 /// Tries to retrieve the number of values for a specific header.
651 ///
652 /// # Arguments
653 ///
654 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
655 ///
656 /// # Returns
657 ///
658 /// - `Option<usize>` - The count of values for the header if exists.
659 #[inline(always)]
660 pub fn try_get_header_length<K>(&self, key: K) -> Option<usize>
661 where
662 K: AsRef<str>,
663 {
664 self.headers.get(key.as_ref()).map(|values| values.len())
665 }
666
667 /// Retrieves the number of values for a specific header.
668 ///
669 /// # Arguments
670 ///
671 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
672 ///
673 /// # Returns
674 ///
675 /// - `usize` - The count of values for the header.
676 ///
677 /// # Panics
678 ///
679 /// This function will panic if the header key is not found.
680 #[inline(always)]
681 pub fn get_header_length<K>(&self, key: K) -> usize
682 where
683 K: AsRef<str>,
684 {
685 self.try_get_header_length(key).unwrap()
686 }
687
688 /// Retrieves the total number of header values across all headers.
689 ///
690 /// # Returns
691 ///
692 /// - `usize` - The total count of all header values.
693 #[inline(always)]
694 pub fn get_headers_values_length(&self) -> usize {
695 self.headers.values().map(|values| values.len()).sum()
696 }
697
698 /// Retrieves the number of unique headers.
699 ///
700 /// # Returns
701 ///
702 /// - `usize` - The count of unique header keys.
703 #[inline(always)]
704 pub fn get_headers_length(&self) -> usize {
705 self.headers.len()
706 }
707
708 /// Checks if a specific header exists.
709 ///
710 /// # Arguments
711 ///
712 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
713 ///
714 /// # Returns
715 ///
716 /// - `bool` - Whether the header exists.
717 #[inline(always)]
718 pub fn has_header<K>(&self, key: K) -> bool
719 where
720 K: AsRef<str>,
721 {
722 self.headers.contains_key(key.as_ref())
723 }
724
725 /// Checks if a header contains a specific value.
726 ///
727 /// # Arguments
728 ///
729 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
730 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
731 ///
732 /// # Returns
733 ///
734 /// - `bool` - Whether the header contains the value.
735 #[inline(always)]
736 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
737 where
738 K: AsRef<str>,
739 V: AsRef<str>,
740 {
741 if let Some(values) = self.headers.get(key.as_ref()) {
742 values.contains(&value.as_ref().to_owned())
743 } else {
744 false
745 }
746 }
747
748 /// Retrieves the body content of the request as a UTF-8 encoded string.
749 ///
750 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as_ref a string.
751 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
752 ///
753 /// # Returns
754 ///
755 /// - `String` - The body content as a string.
756 #[inline(always)]
757 pub fn get_body_string(&self) -> String {
758 String::from_utf8_lossy(self.get_body()).into_owned()
759 }
760
761 /// Deserializes the body content of the request as_ref a specified type `T`.
762 ///
763 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
764 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
765 ///
766 /// # Arguments
767 ///
768 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
769 ///
770 /// # Returns
771 ///
772 /// - `Result<T, serde_json::Error>` - The deserialization result.
773 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
774 where
775 T: DeserializeOwned,
776 {
777 serde_json::from_slice(self.get_body())
778 }
779
780 /// Deserializes the body content of the request as_ref a specified type `T`.
781 ///
782 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
783 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
784 ///
785 /// # Arguments
786 ///
787 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
788 ///
789 /// # Returns
790 ///
791 /// - `T` - The deserialized body content.
792 ///
793 /// # Panics
794 ///
795 /// This function will panic if the deserialization fails.
796 pub fn get_body_json<T>(&self) -> T
797 where
798 T: DeserializeOwned,
799 {
800 self.try_get_body_json().unwrap()
801 }
802
803 /// Converts the request to a formatted string representation.
804 ///
805 /// This method provides a human-readable summary of the request, including its method,
806 /// host, version, path, query parameters, headers, and body information.
807 ///
808 /// # Returns
809 ///
810 /// - `String` - The formatted request details.
811 #[inline(always)]
812 pub fn get_string(&self) -> String {
813 let body: &Vec<u8> = self.get_body();
814 let body_type: &'static str = if std::str::from_utf8(body).is_ok() {
815 PLAIN
816 } else {
817 BINARY
818 };
819 format!(
820 "[Request] => [method]: {}; [host]: {}; [version]: {}; [path]: {}; [querys]: {:?}; [headers]: {:?}; [body]: {} bytes {};",
821 self.get_method(),
822 self.get_host(),
823 self.get_version(),
824 self.get_path(),
825 self.get_querys(),
826 self.get_headers(),
827 body.len(),
828 body_type
829 )
830 }
831
832 /// Retrieves the upgrade type from the request headers.
833 ///
834 /// This method looks for the `UPGRADE` header and attempts to parse its value
835 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
836 /// it returns the default `UpgradeType`.
837 ///
838 /// # Returns
839 ///
840 /// - `UpgradeType` - The parsed upgrade type.
841 #[inline(always)]
842 pub fn get_upgrade_type(&self) -> UpgradeType {
843 let upgrade_type: UpgradeType = self
844 .try_get_header_back(UPGRADE)
845 .and_then(|data| data.parse::<UpgradeType>().ok())
846 .unwrap_or_default();
847 upgrade_type
848 }
849
850 /// Checks whether the WebSocket upgrade is enabled for this request.
851 ///
852 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
853 ///
854 /// # Returns
855 ///
856 /// - `bool` - Whether WebSocket upgrade is enabled.
857 #[inline(always)]
858 pub fn is_ws(&self) -> bool {
859 self.get_upgrade_type().is_ws()
860 }
861
862 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
863 ///
864 /// # Returns
865 ///
866 /// - `bool` - Whether the upgrade type is h2c.
867 #[inline(always)]
868 pub fn is_h2c(&self) -> bool {
869 self.get_upgrade_type().is_h2c()
870 }
871
872 /// Checks if the current upgrade type is TLS (any version).
873 ///
874 /// # Returns
875 ///
876 /// - `bool` - Whether the upgrade type is TLS.
877 #[inline(always)]
878 pub fn is_tls(&self) -> bool {
879 self.get_upgrade_type().is_tls()
880 }
881
882 /// Checks whether the upgrade type is unknown.
883 ///
884 /// # Returns
885 ///
886 /// - `bool` - Whether the upgrade type is unknown.
887 #[inline(always)]
888 pub fn is_unknown_upgrade(&self) -> bool {
889 self.get_upgrade_type().is_unknown()
890 }
891
892 /// Checks if the HTTP version is HTTP/1.1 or higher.
893 ///
894 /// # Returns
895 ///
896 /// - `bool` - Whether the version is HTTP/1.1 or higher.
897 #[inline(always)]
898 pub fn is_http1_1_or_higher(&self) -> bool {
899 self.get_version().is_http1_1_or_higher()
900 }
901
902 /// Checks whether the HTTP version is HTTP/0.9.
903 ///
904 /// # Returns
905 ///
906 /// - `bool` - Whether the version is HTTP/0.9.
907 #[inline(always)]
908 pub fn is_http0_9(&self) -> bool {
909 self.get_version().is_http0_9()
910 }
911
912 /// Checks whether the HTTP version is HTTP/1.0.
913 ///
914 /// # Returns
915 ///
916 /// - `bool` - Whether the version is HTTP/1.0.
917 #[inline(always)]
918 pub fn is_http1_0(&self) -> bool {
919 self.get_version().is_http1_0()
920 }
921
922 /// Checks whether the HTTP version is HTTP/1.1.
923 ///
924 /// # Returns
925 ///
926 /// - `bool` - Whether the version is HTTP/1.1.
927 #[inline(always)]
928 pub fn is_http1_1(&self) -> bool {
929 self.get_version().is_http1_1()
930 }
931
932 /// Checks whether the HTTP version is HTTP/2.
933 ///
934 /// # Returns
935 ///
936 /// - `bool` - Whether the version is HTTP/2.
937 #[inline(always)]
938 pub fn is_http2(&self) -> bool {
939 self.get_version().is_http2()
940 }
941
942 /// Checks whether the HTTP version is HTTP/3.
943 ///
944 /// # Returns
945 ///
946 /// - `bool` - Whether the version is HTTP/3.
947 #[inline(always)]
948 pub fn is_http3(&self) -> bool {
949 self.get_version().is_http3()
950 }
951
952 /// Checks whether the HTTP version is unknown.
953 ///
954 /// # Returns
955 ///
956 /// - `bool` - Whether the version is unknown.
957 #[inline(always)]
958 pub fn is_unknown_version(&self) -> bool {
959 self.get_version().is_unknown()
960 }
961
962 /// Checks whether the version belongs to the HTTP family.
963 ///
964 /// # Returns
965 ///
966 /// - `bool` - Whether the version is HTTP.
967 #[inline(always)]
968 pub fn is_http(&self) -> bool {
969 self.get_version().is_http()
970 }
971
972 /// Checks whether the request method is GET.
973 ///
974 /// # Returns
975 ///
976 /// - `bool` - Whether the method is GET.
977 #[inline(always)]
978 pub fn is_get(&self) -> bool {
979 self.get_method().is_get()
980 }
981
982 /// Checks whether the request method is POST.
983 ///
984 /// # Returns
985 ///
986 /// - `bool` - Whether the method is POST.
987 #[inline(always)]
988 pub fn is_post(&self) -> bool {
989 self.get_method().is_post()
990 }
991
992 /// Checks whether the request method is PUT.
993 ///
994 /// # Returns
995 ///
996 /// - `bool` - Whether the method is PUT.
997 #[inline(always)]
998 pub fn is_put(&self) -> bool {
999 self.get_method().is_put()
1000 }
1001
1002 /// Checks whether the request method is DELETE.
1003 ///
1004 /// # Returns
1005 ///
1006 /// - `bool` - Whether the method is DELETE.
1007 #[inline(always)]
1008 pub fn is_delete(&self) -> bool {
1009 self.get_method().is_delete()
1010 }
1011
1012 /// Checks whether the request method is PATCH.
1013 ///
1014 /// # Returns
1015 ///
1016 /// - `bool` - Whether the method is PATCH.
1017 #[inline(always)]
1018 pub fn is_patch(&self) -> bool {
1019 self.get_method().is_patch()
1020 }
1021
1022 /// Checks whether the request method is HEAD.
1023 ///
1024 /// # Returns
1025 ///
1026 /// - `bool` - Whether the method is HEAD.
1027 #[inline(always)]
1028 pub fn is_head(&self) -> bool {
1029 self.get_method().is_head()
1030 }
1031
1032 /// Checks whether the request method is OPTIONS.
1033 ///
1034 /// # Returns
1035 ///
1036 /// - `bool` - Whether the method is OPTIONS.
1037 #[inline(always)]
1038 pub fn is_options(&self) -> bool {
1039 self.get_method().is_options()
1040 }
1041
1042 /// Checks whether the request method is CONNECT.
1043 ///
1044 /// # Returns
1045 ///
1046 /// - `bool` - Whether the method is CONNECT.
1047 #[inline(always)]
1048 pub fn is_connect(&self) -> bool {
1049 self.get_method().is_connect()
1050 }
1051
1052 /// Checks whether the request method is TRACE.
1053 ///
1054 /// # Returns
1055 ///
1056 /// - `bool` - Whether the method is TRACE.
1057 #[inline(always)]
1058 pub fn is_trace(&self) -> bool {
1059 self.get_method().is_trace()
1060 }
1061
1062 /// Checks whether the request method is UNKNOWN.
1063 ///
1064 /// # Returns
1065 ///
1066 /// - `bool` - Whether the method is UNKNOWN.
1067 #[inline(always)]
1068 pub fn is_unknown_method(&self) -> bool {
1069 self.get_method().is_unknown()
1070 }
1071
1072 /// Determines if a keep-alive connection should be enabled for this request.
1073 ///
1074 /// This function checks the `Connection` header and the HTTP version to determine
1075 /// if keep-alive should be enabled. The logic is as follows:
1076 ///
1077 /// 1. If the `Connection` header exists:
1078 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1079 /// - Returns `false` if the header value is "close" (case-insensitive).
1080 /// 2. If no `Connection` header is present:
1081 /// - Returns `true` if the HTTP version is 1.1 or higher.
1082 /// - Returns `false` otherwise.
1083 ///
1084 /// # Returns
1085 ///
1086 /// - `bool` - Whether keep-alive should be enabled.
1087 #[inline(always)]
1088 pub fn is_enable_keep_alive(&self) -> bool {
1089 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1090 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1091 return true;
1092 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1093 return self.is_ws();
1094 }
1095 }
1096 self.is_http1_1_or_higher() || self.is_ws()
1097 }
1098
1099 /// Determines if keep-alive should be disabled for this request.
1100 ///
1101 /// # Returns
1102 ///
1103 /// - `bool` - Whether keep-alive should be disabled.
1104 #[inline(always)]
1105 pub fn is_disable_keep_alive(&self) -> bool {
1106 !self.is_enable_keep_alive()
1107 }
1108}