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