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 #[inline(always)]
12 fn default() -> Self {
13 RequestError::Unknown(HttpStatus::InternalServerError)
14 }
15}
16
17/// Converts an I/O error to a `RequestError`.
18///
19/// Maps connection reset and aborted errors to `ClientDisconnected`,
20/// all other I/O errors are mapped to `ReadConnection`.
21impl From<std::io::Error> for RequestError {
22 /// Converts an I/O error to a `RequestError`.
23 ///
24 /// # Arguments
25 ///
26 /// - `std::io::Error`: The I/O error to convert.
27 ///
28 /// # Returns
29 ///
30 /// - `RequestError`: The corresponding request error.
31 #[inline(always)]
32 fn from(error: std::io::Error) -> Self {
33 let kind: ErrorKind = error.kind();
34 if kind == ErrorKind::ConnectionReset || kind == ErrorKind::ConnectionAborted {
35 return RequestError::ClientDisconnected(HttpStatus::BadRequest);
36 }
37 RequestError::ReadConnection(HttpStatus::BadRequest)
38 }
39}
40
41/// Converts a timeout elapsed error to a `RequestError`.
42///
43/// Maps timeout errors to `ReadTimeout` with `HttpStatus::RequestTimeout`.
44impl From<Elapsed> for RequestError {
45 /// Converts a timeout elapsed error to a `RequestError`.
46 ///
47 /// # Arguments
48 ///
49 /// - `Elapsed`: The elapsed error to convert.
50 ///
51 /// # Returns
52 ///
53 /// - `RequestError`: The corresponding request error as `ReadTimeout`.
54 #[inline(always)]
55 fn from(_: Elapsed) -> Self {
56 RequestError::ReadTimeout(HttpStatus::RequestTimeout)
57 }
58}
59
60/// Converts a parse int error to a `RequestError`.
61///
62/// Maps parse int errors to `InvalidContentLength` with `HttpStatus::BadRequest`.
63impl From<ParseIntError> for RequestError {
64 /// Converts a parse int error to a `RequestError`.
65 ///
66 /// # Arguments
67 ///
68 /// - `ParseIntError`: The parse error to convert.
69 ///
70 /// # Returns
71 ///
72 /// - `RequestError`: The corresponding request error as `InvalidContentLength`.
73 #[inline(always)]
74 fn from(_: ParseIntError) -> Self {
75 RequestError::InvalidContentLength(HttpStatus::BadRequest)
76 }
77}
78
79/// Converts a response error to a `RequestError`.
80///
81/// Maps response errors to `WriteTimeout` with `HttpStatus::InternalServerError`.
82impl From<ResponseError> for RequestError {
83 /// Converts a response error to a `RequestError`.
84 ///
85 /// # Arguments
86 ///
87 /// - `ResponseError`: The response error to convert.
88 ///
89 /// # Returns
90 ///
91 /// - `RequestError`: The corresponding request error as `WriteTimeout`.
92 #[inline(always)]
93 fn from(_: ResponseError) -> Self {
94 RequestError::WriteTimeout(HttpStatus::InternalServerError)
95 }
96}
97
98impl RequestError {
99 /// Gets the HTTP status associated with this error.
100 ///
101 /// Returns the HttpStatus enum variant that corresponds to this error.
102 ///
103 /// # Returns
104 ///
105 /// - `HttpStatus` - The HTTP status associated with this error.
106 pub fn get_http_status(&self) -> HttpStatus {
107 match self {
108 Self::HttpRead(status) => *status,
109 Self::GetTcpStream(status) => *status,
110 Self::GetTlsStream(status) => *status,
111 Self::ReadConnection(status) => *status,
112 Self::RequestAborted(status) => *status,
113 Self::TlsStreamConnect(status) => *status,
114 Self::NeedOpenRedirect(status) => *status,
115 Self::MaxRedirectTimes(status) => *status,
116 Self::MethodsNotSupport(status) => *status,
117 Self::RedirectInvalidUrl(status) => *status,
118 Self::ClientDisconnected(status) => *status,
119 Self::RedirectUrlDeadLoop(status) => *status,
120 Self::ClientClosedConnection(status) => *status,
121 Self::IncompleteWebSocketFrame(status) => *status,
122 Self::RequestTooLong(status) => *status,
123 Self::PathTooLong(status) => *status,
124 Self::QueryTooLong(status) => *status,
125 Self::HeaderLineTooLong(status) => *status,
126 Self::TooManyHeaders(status) => *status,
127 Self::HeaderKeyTooLong(status) => *status,
128 Self::HeaderValueTooLong(status) => *status,
129 Self::ContentLengthTooLarge(status) => *status,
130 Self::InvalidContentLength(status) => *status,
131 Self::InvalidUrlScheme(status) => *status,
132 Self::InvalidUrlHost(status) => *status,
133 Self::InvalidUrlPort(status) => *status,
134 Self::InvalidUrlPath(status) => *status,
135 Self::InvalidUrlQuery(status) => *status,
136 Self::InvalidUrlFragment(status) => *status,
137 Self::ReadTimeout(status) => *status,
138 Self::WriteTimeout(status) => *status,
139 Self::TcpConnectionFailed(status) => *status,
140 Self::TlsHandshakeFailed(status) => *status,
141 Self::TlsCertificateInvalid(status) => *status,
142 Self::WebSocketFrameTooLarge(status) => *status,
143 Self::WebSocketOpcodeUnsupported(status) => *status,
144 Self::WebSocketMaskMissing(status) => *status,
145 Self::WebSocketPayloadCorrupted(status) => *status,
146 Self::WebSocketInvalidUtf8(status) => *status,
147 Self::WebSocketInvalidCloseCode(status) => *status,
148 Self::WebSocketInvalidExtension(status) => *status,
149 Self::HttpRequestPartsInsufficient(status) => *status,
150 Self::TcpStreamConnect(status) => *status,
151 Self::TlsConnectorBuild(status) => *status,
152 Self::InvalidUrl(status) => *status,
153 Self::ConfigReadError(status) => *status,
154 Self::TcpStreamConnectString(status) => *status,
155 Self::TlsConnectorBuildString(status) => *status,
156 Self::Request(_) => HttpStatus::BadRequest,
157 Self::Unknown(status) => *status,
158 }
159 }
160
161 /// Gets the numeric HTTP status code associated with this error.
162 ///
163 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
164 ///
165 /// # Returns
166 ///
167 /// - `ResponseStatusCode` - The numeric HTTP status code.
168 pub fn get_http_status_code(&self) -> ResponseStatusCode {
169 self.get_http_status().code()
170 }
171}
172
173/// Implementation of `Default` trait for `RequestConfig`.
174impl Default for RequestConfig {
175 /// Creates a new `RequestConfig` with default secure settings.
176 ///
177 /// This constructor initializes the configuration with standard security limits
178 /// suitable for most HTTP request parsing scenarios.
179 ///
180 /// # Returns
181 ///
182 /// - `Self` - A new `RequestConfig` instance with default settings.
183 #[inline(always)]
184 fn default() -> Self {
185 Self {
186 buffer_size: DEFAULT_BUFFER_SIZE,
187 max_path_size: DEFAULT_MAX_PATH_SIZE,
188 max_header_count: DEFAULT_MAX_HEADER_COUNT,
189 max_header_key_size: DEFAULT_MAX_HEADER_KEY_SIZE,
190 max_header_value_size: DEFAULT_MAX_HEADER_VALUE_SIZE,
191 max_body_size: DEFAULT_MAX_BODY_SIZE,
192 read_timeout_ms: DEFAULT_READ_TIMEOUT_MS,
193 }
194 }
195}
196
197impl RequestConfig {
198 /// Creates a new `RequestConfig` from a JSON string.
199 ///
200 /// # Arguments
201 ///
202 /// - `AsRef<str>` - The configuration.
203 ///
204 /// # Returns
205 ///
206 /// - `Result<RequestConfig, serde_json::Error>` - The parsed `RequestConfig` or an error.
207 pub fn from_json<C>(json: C) -> Result<RequestConfig, serde_json::Error>
208 where
209 C: AsRef<str>,
210 {
211 serde_json::from_str(json.as_ref())
212 }
213
214 /// Creates a new `RequestConfig` with low-security settings.
215 ///
216 /// This constructor initializes the configuration with less restrictive limits
217 /// for environments where higher limits are needed.
218 ///
219 /// # Returns
220 ///
221 /// - `Self` - A new `RequestConfig` instance with low-security settings.
222 #[inline(always)]
223 pub fn low_security() -> Self {
224 Self {
225 buffer_size: DEFAULT_LOW_SECURITY_BUFFER_SIZE,
226 max_path_size: DEFAULT_LOW_SECURITY_MAX_PATH_SIZE,
227 max_header_count: DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT,
228 max_header_key_size: DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE,
229 max_header_value_size: DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE,
230 max_body_size: DEFAULT_LOW_SECURITY_MAX_BODY_SIZE,
231 read_timeout_ms: DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS,
232 }
233 }
234
235 /// Creates a new `RequestConfig` with high-security settings.
236 ///
237 /// This constructor initializes the configuration with more restrictive limits
238 /// to provide maximum protection against various attacks in high-risk environments.
239 ///
240 /// # Returns
241 ///
242 /// - `Self` - A new `RequestConfig` instance with high-security settings.
243 #[inline(always)]
244 pub fn high_security() -> Self {
245 Self {
246 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
247 max_path_size: DEFAULT_HIGH_SECURITY_MAX_PATH_SIZE,
248 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
249 max_header_key_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_SIZE,
250 max_header_value_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_SIZE,
251 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
252 read_timeout_ms: DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS,
253 }
254 }
255}
256
257/// Provides a default value for `Request`.
258///
259/// Returns a new `Request` instance with all fields initialized to their default values.
260impl Default for Request {
261 #[inline(always)]
262 fn default() -> Self {
263 Self {
264 method: Method::default(),
265 host: String::new(),
266 version: HttpVersion::default(),
267 path: String::new(),
268 querys: hash_map_xx_hash3_64(),
269 headers: hash_map_xx_hash3_64(),
270 body: Vec::new(),
271 }
272 }
273}
274
275impl Http {
276 /// Parses the first line of HTTP request into method, path, and version components.
277 ///
278 /// # Arguments
279 ///
280 /// - `&str`: The first line string of HTTP request to parse.
281 ///
282 /// # Returns
283 ///
284 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>`: A tuple containing:
285 /// - The parsed HTTP method
286 /// - The full path string
287 /// - The parsed HTTP version
288 /// - Or an error if parsing fails
289 #[inline(always)]
290 fn parse_first_line(line: &str) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
291 let mut parts = line.split_whitespace();
292 let method_str: &str = parts
293 .next()
294 .ok_or(RequestError::HttpRequestPartsInsufficient(
295 HttpStatus::BadRequest,
296 ))?;
297 let full_path: &str = parts
298 .next()
299 .ok_or(RequestError::HttpRequestPartsInsufficient(
300 HttpStatus::BadRequest,
301 ))?;
302 let version_str: &str = parts
303 .next()
304 .ok_or(RequestError::HttpRequestPartsInsufficient(
305 HttpStatus::BadRequest,
306 ))?;
307 let method: RequestMethod = method_str
308 .parse::<RequestMethod>()
309 .unwrap_or_else(|_| Method::Unknown(method_str.to_string()));
310 let version: RequestVersion = version_str
311 .parse::<RequestVersion>()
312 .unwrap_or_else(|_| RequestVersion::Unknown(version_str.to_string()));
313 Ok((method, full_path, version))
314 }
315
316 /// Validates the path length against the maximum allowed size.
317 ///
318 /// # Arguments
319 ///
320 /// - `&str`: The path string to check.
321 /// - `usize`: The maximum allowed path size.
322 ///
323 /// # Returns
324 ///
325 /// - `Result<(), RequestError>`: Ok if valid, or an error if the path is too long.
326 #[inline(always)]
327 fn check_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
328 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
329 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
330 }
331 Ok(())
332 }
333
334 /// Parses the query string from the full path.
335 ///
336 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
337 /// ensuring proper parsing when both are present.
338 ///
339 /// # Arguments
340 ///
341 /// - `&str`: The full path string containing the query.
342 /// - `Option<usize>`: The index of the query separator (`?`), if present.
343 /// - `Option<usize>`: The index of the hash separator (`#`), if present.
344 ///
345 /// # Returns
346 ///
347 /// - `&str`: The parsed query string slice, or empty string if no query.
348 #[inline(always)]
349 fn get_query_slice<'a>(
350 path: &'a str,
351 query_index: Option<usize>,
352 hash_index: Option<usize>,
353 ) -> &'a str {
354 query_index.map_or(EMPTY_STR, |i: usize| {
355 let temp: &'a str = &path[i + 1..];
356 match hash_index {
357 None => temp,
358 Some(hash_idx) if hash_idx <= i => temp,
359 Some(hash_idx) => &temp[..hash_idx - i - 1],
360 }
361 })
362 }
363
364 /// Parses the request path without query string or hash fragment.
365 ///
366 /// # Arguments
367 ///
368 /// - `&str`: The full path string.
369 /// - `Option<usize>`: The index of the query separator (`?`), if present.
370 /// - `Option<usize>`: The index of the hash separator (`#`), if present.
371 ///
372 /// # Returns
373 ///
374 /// - `RequestPath`: The request path without query or hash.
375 #[inline(always)]
376 fn parse_path(
377 path: &str,
378 query_index: Option<usize>,
379 hash_index: Option<usize>,
380 ) -> RequestPath {
381 match query_index.or(hash_index) {
382 Some(i) => path[..i].to_owned(),
383 None => path.to_owned(),
384 }
385 }
386
387 /// Parses a query string as_ref key-value pairs.
388 ///
389 /// Expects format "key1=value1&key2=value2". Empty values are allowed.
390 ///
391 /// # Arguments
392 ///
393 /// - `&str` - The query string to parse.
394 ///
395 /// # Returns
396 ///
397 /// - `RequestQuerys` - The parsed query parameters.
398 #[inline(always)]
399 fn parse_querys(query: &str) -> RequestQuerys {
400 let estimated_capacity: usize = query.matches(AND).count() + 1;
401 let mut query_map: RequestQuerys = HashMapXxHash3_64::with_capacity_and_hasher(
402 estimated_capacity,
403 BuildHasherDefault::default(),
404 );
405 for pair in query.split(AND) {
406 if let Some((key, value)) = pair.split_once(EQUAL) {
407 if !key.is_empty() {
408 query_map.insert(key.to_string(), value.to_string());
409 }
410 } else if !pair.is_empty() {
411 query_map.insert(pair.to_string(), String::new());
412 }
413 }
414 query_map
415 }
416
417 /// Checks if the header count exceeds the maximum allowed.
418 ///
419 /// # Arguments
420 ///
421 /// - `usize`: The current number of headers parsed.
422 /// - `usize`: The maximum allowed number of headers.
423 ///
424 /// # Returns
425 ///
426 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
427 #[inline(always)]
428 fn check_header_count(count: usize, max_count: usize) -> Result<(), RequestError> {
429 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
430 return Err(RequestError::TooManyHeaders(
431 HttpStatus::RequestHeaderFieldsTooLarge,
432 ));
433 }
434 Ok(())
435 }
436
437 /// Checks if a header key exceeds the maximum allowed length.
438 ///
439 /// # Arguments
440 ///
441 /// - `&str`: The header key to check.
442 /// - `usize`: The maximum allowed length for a header key.
443 ///
444 /// # Returns
445 ///
446 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
447 #[inline(always)]
448 fn check_header_key_size(key: &str, max_size: usize) -> Result<(), RequestError> {
449 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
450 return Err(RequestError::HeaderKeyTooLong(
451 HttpStatus::RequestHeaderFieldsTooLarge,
452 ));
453 }
454 Ok(())
455 }
456
457 /// Checks if a header value exceeds the maximum allowed length.
458 ///
459 /// # Arguments
460 ///
461 /// - `&str`: The header value to check.
462 /// - `usize`: The maximum allowed length for a header value.
463 ///
464 /// # Returns
465 ///
466 /// - `Result<(), RequestError>`: Returns an error if the limit is exceeded and not in low security mode.
467 #[inline(always)]
468 fn check_header_value_size(value: &str, max_size: usize) -> Result<(), RequestError> {
469 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
470 return Err(RequestError::HeaderValueTooLong(
471 HttpStatus::RequestHeaderFieldsTooLarge,
472 ));
473 }
474 Ok(())
475 }
476
477 /// Parses the Content-Length header value and checks it against max body size.
478 ///
479 /// # Arguments
480 ///
481 /// - `&str`: The Content-Length header value string.
482 /// - `usize`: The maximum allowed body size.
483 ///
484 /// # Returns
485 ///
486 /// - `Result<usize, RequestError>`: The parsed content length or an error.
487 #[inline(always)]
488 fn check_body_size(value: &str, max_size: usize) -> Result<usize, RequestError> {
489 let length: usize = value.parse::<usize>()?;
490 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
491 return Err(RequestError::ContentLengthTooLarge(
492 HttpStatus::PayloadTooLarge,
493 ));
494 }
495 Ok(length)
496 }
497
498 /// Parses HTTP headers from a buffered reader.
499 ///
500 /// This method reads header lines from the provided buffered reader until an empty line
501 /// is encountered, which indicates the end of headers. It checks header count, length,
502 /// and content according to the provided configuration.
503 ///
504 /// # Arguments
505 ///
506 /// - `&mut AsyncBufReadExt + Unpin`: A mutable reference to a buffered reader implementing `AsyncBufReadExt`.
507 /// - `&RequestConfig`: Configuration for security limits and buffer settings.
508 ///
509 /// # Returns
510 ///
511 /// - `Result<(RequestHeaders, RequestHost, usize), RequestError>`: A tuple containing:
512 /// - The parsed headers as a hash map
513 /// - The host value parsed from the Host header
514 /// - The content length parsed from the Content-Length header
515 /// - Or an error if parsing fails
516 async fn parse_headers<R>(
517 reader: &mut R,
518 config: &RequestConfig,
519 ) -> Result<(RequestHeaders, RequestHost, usize), RequestError>
520 where
521 R: AsyncBufReadExt + Unpin,
522 {
523 let buffer_size: usize = config.get_buffer_size();
524 let max_header_count: usize = config.get_max_header_count();
525 let max_header_key_size: usize = config.get_max_header_key_size();
526 let max_header_value_size: usize = config.get_max_header_value_size();
527 let max_body_size: usize = config.get_max_body_size();
528 let mut headers: RequestHeaders =
529 HashMapXxHash3_64::with_capacity_and_hasher(B_16, BuildHasherDefault::default());
530 let mut host: RequestHost = String::new();
531 let mut content_size: usize = 0;
532 let mut header_count: usize = 0;
533 let mut header_line_buffer: String = String::with_capacity(buffer_size);
534 loop {
535 header_line_buffer.clear();
536 AsyncBufReadExt::read_line(reader, &mut header_line_buffer).await?;
537 let header_line: &str = header_line_buffer.trim();
538 if header_line.is_empty() {
539 break;
540 }
541 header_count += 1;
542 Self::check_header_count(header_count, max_header_count)?;
543 let (key_part, value_part): (&str, &str) = match header_line.split_once(COLON) {
544 Some(parts) => parts,
545 None => continue,
546 };
547 let key_trimmed: &str = key_part.trim();
548 if key_trimmed.is_empty() {
549 continue;
550 }
551 let key: String = key_trimmed.to_ascii_lowercase();
552 Self::check_header_key_size(&key, max_header_key_size)?;
553 let value: String = value_part.trim().to_string();
554 Self::check_header_value_size(&value, max_header_value_size)?;
555 match key.as_str() {
556 HOST => host = value.clone(),
557 CONTENT_LENGTH => {
558 content_size = Self::check_body_size(&value, max_body_size)?;
559 }
560 _ => {}
561 }
562 headers.entry(key).or_default().push_back(value);
563 }
564 Ok((headers, host, content_size))
565 }
566
567 /// Reads the request body from the buffered reader.
568 ///
569 /// # Arguments
570 ///
571 /// - `&mut BufReader<&mut TcpStream>`: The buffered reader to read from.
572 /// - `usize`: The expected content size.
573 ///
574 /// # Returns
575 ///
576 /// - `Result<RequestBody, RequestError>`: The body bytes or an error.
577 #[inline(always)]
578 async fn parse_body(
579 reader: &mut BufReader<&mut TcpStream>,
580 content_size: usize,
581 ) -> Result<RequestBody, RequestError> {
582 let mut body: RequestBody = Vec::with_capacity(content_size);
583 if content_size > 0 {
584 body.resize(content_size, 0);
585 AsyncReadExt::read_exact(reader, &mut body).await?;
586 }
587 Ok(body)
588 }
589
590 /// Parses the HTTP request content from the stream.
591 ///
592 /// This is an internal helper function that performs the actual parsing.
593 ///
594 /// # Arguments
595 ///
596 /// - `&ArcRwLock<TcpStream>`: The TCP stream to read from.
597 /// - `&RequestConfig`: Configuration for security limits and buffer settings.
598 ///
599 /// # Returns
600 ///
601 /// - `Result<Request, RequestError>`: The parsed request or an error.
602 async fn parse_from_stream(
603 stream: &ArcRwLockStream,
604 config: &RequestConfig,
605 ) -> Result<Request, RequestError> {
606 let buffer_size: usize = config.get_buffer_size();
607 let max_path_size: usize = config.get_max_path_size();
608 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.write().await;
609 let reader: &mut BufReader<&mut TcpStream> =
610 &mut BufReader::with_capacity(buffer_size, &mut buf_stream);
611 let mut line: String = String::with_capacity(buffer_size);
612 AsyncBufReadExt::read_line(reader, &mut line).await?;
613 let (method, path, version): (RequestMethod, &str, RequestVersion) =
614 Self::parse_first_line(&line)?;
615 Self::check_path_size(path, max_path_size)?;
616 let hash_index: Option<usize> = path.find(HASH);
617 let query_index: Option<usize> = path.find(QUERY);
618 let query_slice: &str = Self::get_query_slice(path, query_index, hash_index);
619 let querys: RequestQuerys = Self::parse_querys(query_slice);
620 let path: RequestPath = Self::parse_path(path, query_index, hash_index);
621 let (headers, host, content_size): (RequestHeaders, RequestHost, usize) =
622 Self::parse_headers(reader, config).await?;
623 let body: RequestBody = Self::parse_body(reader, content_size).await?;
624 Ok(Request {
625 method,
626 host,
627 version,
628 path,
629 querys,
630 headers,
631 body,
632 })
633 }
634}
635
636impl Ws {
637 /// Reads data from the stream with optional timeout handling.
638 ///
639 /// # Arguments
640 ///
641 /// - `&ArcRwLockStream`: The TCP stream to read from.
642 /// - `&mut [u8]`: The buffer to read data into.
643 /// - `Option<Duration>`: The optional timeout duration. If Some, timeout is applied; if None, no timeout.
644 /// - `&mut bool`: Mutable reference to track if we got a client response.
645 ///
646 /// # Returns
647 ///
648 /// - `Result<Option<usize>, RequestError>`: The number of bytes read, None for timeout/ping, or an error.
649 async fn read(
650 stream: &ArcRwLockStream,
651 buffer: &mut [u8],
652 duration_opt: Option<Duration>,
653 is_client_response: &mut bool,
654 ) -> Result<Option<usize>, RequestError> {
655 if let Some(duration) = duration_opt {
656 return match timeout(duration, stream.write().await.read(buffer)).await {
657 Ok(result) => match result {
658 Ok(len) => Ok(Some(len)),
659 Err(error) => Err(error.into()),
660 },
661 Err(error) => {
662 if !*is_client_response {
663 return Err(error.into());
664 }
665 *is_client_response = false;
666 stream.try_send_body(&PING_FRAME).await?;
667 Ok(None)
668 }
669 };
670 }
671 match stream.write().await.read(buffer).await {
672 Ok(len) => Ok(Some(len)),
673 Err(error) => Err(error.into()),
674 }
675 }
676
677 /// Handles a decoded WebSocket Text or Binary frame and accumulates payload data.
678 ///
679 /// # Arguments
680 ///
681 /// - `&Request`: The request to update on completion.
682 /// - `&WebSocketFrame`: The decoded WebSocket frame.
683 /// - `&mut Vec<u8>`: The accumulated frame data.
684 ///
685 /// # Returns
686 ///
687 /// - `Result<Option<Request>, RequestError>`: Some(request) if frame is complete, None to continue, or error.
688 #[inline(always)]
689 fn parse_frame(
690 request: &Request,
691 frame: &WebSocketFrame,
692 full_frame: &mut Vec<u8>,
693 ) -> Result<Option<Request>, RequestError> {
694 let payload_data: &[u8] = frame.get_payload_data();
695 full_frame.extend_from_slice(payload_data);
696 if *frame.get_fin() {
697 let mut result: Request = request.clone();
698 result.body = full_frame.clone();
699 return Ok(Some(result));
700 }
701 Ok(None)
702 }
703}
704
705impl Request {
706 /// Parses an HTTP request from a TCP stream.
707 ///
708 /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
709 /// If the timeout is DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS, no timeout is applied.
710 ///
711 /// # Arguments
712 ///
713 /// - `&ArcRwLock<TcpStream>` - The TCP stream to read from.
714 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
715 ///
716 /// # Returns
717 ///
718 /// - `Result<Request, RequestError>` - The parsed request or an error.
719 pub async fn http_from_stream(
720 stream: &ArcRwLockStream,
721 config: &RequestConfig,
722 ) -> Result<Request, RequestError> {
723 let timeout_ms: u64 = config.get_read_timeout_ms();
724 if timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
725 return Http::parse_from_stream(stream, config).await;
726 }
727 let duration: Duration = Duration::from_millis(timeout_ms);
728 timeout(duration, Http::parse_from_stream(stream, config)).await?
729 }
730
731 /// Parses a WebSocket request from a TCP stream.
732 ///
733 /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
734 /// If the timeout is DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS, no timeout is applied.
735 ///
736 /// # Arguments
737 ///
738 /// - `&ArcRwLock<TcpStream>`: The TCP stream to read from.
739 /// - `&RequestConfig`: Configuration for security limits and buffer settings.
740 ///
741 /// # Returns
742 ///
743 /// - `Result<Request, RequestError>`: The parsed WebSocket request or an error.
744 pub async fn ws_from_stream(
745 &self,
746 stream: &ArcRwLockStream,
747 config: &RequestConfig,
748 ) -> Result<Request, RequestError> {
749 let buffer_size: usize = config.get_buffer_size();
750 let read_timeout_ms: u64 = config.get_read_timeout_ms();
751 let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
752 let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
753 let mut full_frame: Vec<u8> = Vec::new();
754 let mut is_client_response: bool = false;
755 let duration_opt: Option<Duration> =
756 if read_timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
757 None
758 } else {
759 let adjusted_timeout_ms: u64 = (read_timeout_ms >> 1) + (read_timeout_ms & 1);
760 Some(Duration::from_millis(adjusted_timeout_ms))
761 };
762 loop {
763 let len: usize = match Ws::read(
764 stream,
765 &mut temp_buffer,
766 duration_opt,
767 &mut is_client_response,
768 )
769 .await
770 {
771 Ok(Some(len)) => len,
772 Ok(None) => continue,
773 Err(error) => return Err(error),
774 };
775 if len == 0 {
776 return Err(RequestError::IncompleteWebSocketFrame(
777 HttpStatus::BadRequest,
778 ));
779 }
780 dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
781 while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
782 is_client_response = true;
783 dynamic_buffer.drain(0..consumed);
784 match frame.get_opcode() {
785 WebSocketOpcode::Close => {
786 return Err(RequestError::ClientClosedConnection(HttpStatus::BadRequest));
787 }
788 WebSocketOpcode::Ping | WebSocketOpcode::Pong => continue,
789 WebSocketOpcode::Text | WebSocketOpcode::Binary => {
790 match Ws::parse_frame(self, &frame, &mut full_frame) {
791 Ok(Some(result)) => return Ok(result),
792 Ok(None) => continue,
793 Err(error) => return Err(error),
794 }
795 }
796 _ => {
797 return Err(RequestError::WebSocketOpcodeUnsupported(
798 HttpStatus::NotImplemented,
799 ));
800 }
801 }
802 }
803 }
804 }
805
806 /// Tries to get a query parameter value by key.
807 ///
808 /// The key type must implement AsRef<str> conversion.
809 ///
810 /// # Arguments
811 ///
812 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
813 ///
814 /// # Returns
815 ///
816 /// - `Option<RequestQuerysValue>` - The parameter value if exists.
817 #[inline(always)]
818 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
819 where
820 K: AsRef<str>,
821 {
822 self.querys.get(key.as_ref()).cloned()
823 }
824
825 /// Gets a query parameter value by key.
826 ///
827 /// The key type must implement AsRef<str> conversion.
828 ///
829 /// # Arguments
830 ///
831 /// - `AsRef<str>` - The query parameter key (implements AsRef<str>).
832 ///
833 /// # Returns
834 ///
835 /// - `RequestQuerysValue` - The parameter value if exists.
836 ///
837 /// # Panics
838 ///
839 /// This function will panic if the query parameter key is not found.
840 #[inline(always)]
841 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
842 where
843 K: AsRef<str>,
844 {
845 self.try_get_query(key).unwrap()
846 }
847
848 /// Tries to retrieve the value of a request header by its key.
849 ///
850 /// # Arguments
851 ///
852 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
853 ///
854 /// # Returns
855 ///
856 /// - `Option<RequestHeadersValue>` - The optional header values.
857 #[inline(always)]
858 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
859 where
860 K: AsRef<str>,
861 {
862 self.headers.get(key.as_ref()).cloned()
863 }
864
865 /// Retrieves the value of a request header by its key.
866 ///
867 /// # Arguments
868 ///
869 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
870 ///
871 /// # Returns
872 ///
873 /// - `RequestHeadersValue` - The optional header values.
874 ///
875 /// # Panics
876 ///
877 /// This function will panic if the header key is not found.
878 #[inline(always)]
879 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
880 where
881 K: AsRef<str>,
882 {
883 self.try_get_header(key).unwrap()
884 }
885
886 /// Tries to retrieve the first value of a request header by its key.
887 ///
888 /// # Arguments
889 ///
890 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
891 ///
892 /// # Returns
893 ///
894 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
895 #[inline(always)]
896 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
897 where
898 K: AsRef<str>,
899 {
900 self.headers
901 .get(key.as_ref())
902 .and_then(|values| values.front().cloned())
903 }
904
905 /// Retrieves the first value of a request header by its key.
906 ///
907 /// # Arguments
908 ///
909 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
910 ///
911 /// # Returns
912 ///
913 /// - `RequestHeadersValueItem` - The first header value if exists.
914 ///
915 /// # Panics
916 ///
917 /// This function will panic if the header key is not found.
918 #[inline(always)]
919 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
920 where
921 K: AsRef<str>,
922 {
923 self.try_get_header_front(key).unwrap()
924 }
925
926 /// Tries to retrieve the last value of a request header by its key.
927 ///
928 /// # Arguments
929 ///
930 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
931 ///
932 /// # Returns
933 ///
934 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
935 #[inline(always)]
936 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
937 where
938 K: AsRef<str>,
939 {
940 self.headers
941 .get(key.as_ref())
942 .and_then(|values| values.back().cloned())
943 }
944
945 /// Retrieves the last value of a request header by its key.
946 ///
947 /// # Arguments
948 ///
949 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
950 ///
951 /// # Returns
952 ///
953 /// - `RequestHeadersValueItem` - The last header value if exists.
954 ///
955 /// # Panics
956 ///
957 /// This function will panic if the header key is not found.
958 #[inline(always)]
959 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
960 where
961 K: AsRef<str>,
962 {
963 self.try_get_header_back(key).unwrap()
964 }
965
966 /// Tries to retrieve the number of values for a specific header.
967 ///
968 /// # Arguments
969 ///
970 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
971 ///
972 /// # Returns
973 ///
974 /// - `Option<usize>` - The count of values for the header if exists.
975 #[inline(always)]
976 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
977 where
978 K: AsRef<str>,
979 {
980 self.headers.get(key.as_ref()).map(|values| values.len())
981 }
982
983 /// Retrieves the number of values for a specific header.
984 ///
985 /// # Arguments
986 ///
987 /// - `AsRef<str>` - The header's key (must implement AsRef<str>).
988 ///
989 /// # Returns
990 ///
991 /// - `usize` - The count of values for the header.
992 ///
993 /// # Panics
994 ///
995 /// This function will panic if the header key is not found.
996 #[inline(always)]
997 pub fn get_header_size<K>(&self, key: K) -> usize
998 where
999 K: AsRef<str>,
1000 {
1001 self.try_get_header_size(key).unwrap()
1002 }
1003
1004 /// Retrieves the total number of header values across all headers.
1005 ///
1006 /// # Returns
1007 ///
1008 /// - `usize` - The total count of all header values.
1009 #[inline(always)]
1010 pub fn get_headers_values_size(&self) -> usize {
1011 self.headers.values().map(|values| values.len()).sum()
1012 }
1013
1014 /// Retrieves the number of unique headers.
1015 ///
1016 /// # Returns
1017 ///
1018 /// - `usize` - The count of unique header keys.
1019 #[inline(always)]
1020 pub fn get_headers_size(&self) -> usize {
1021 self.headers.len()
1022 }
1023
1024 /// Checks if a specific header exists.
1025 ///
1026 /// # Arguments
1027 ///
1028 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
1029 ///
1030 /// # Returns
1031 ///
1032 /// - `bool` - Whether the header exists.
1033 #[inline(always)]
1034 pub fn has_header<K>(&self, key: K) -> bool
1035 where
1036 K: AsRef<str>,
1037 {
1038 self.headers.contains_key(key.as_ref())
1039 }
1040
1041 /// Checks if a header contains a specific value.
1042 ///
1043 /// # Arguments
1044 ///
1045 /// - `AsRef<str>` - The header key to check (must implement AsRef<str>).
1046 /// - `AsRef<str>` - The value to search for (must implement AsRef<str>).
1047 ///
1048 /// # Returns
1049 ///
1050 /// - `bool` - Whether the header contains the value.
1051 #[inline(always)]
1052 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
1053 where
1054 K: AsRef<str>,
1055 V: AsRef<str>,
1056 {
1057 if let Some(values) = self.headers.get(key.as_ref()) {
1058 values.iter().any(|v| v == value.as_ref())
1059 } else {
1060 false
1061 }
1062 }
1063
1064 /// Retrieves the upgrade type from the request headers.
1065 ///
1066 /// This method looks for the `UPGRADE` header and attempts to parse its value
1067 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
1068 /// it returns the default `UpgradeType`.
1069 ///
1070 /// # Returns
1071 ///
1072 /// - `UpgradeType` - The parsed upgrade type.
1073 #[inline(always)]
1074 pub fn get_upgrade_type(&self) -> UpgradeType {
1075 self.try_get_header_back(UPGRADE)
1076 .and_then(|data| data.parse::<UpgradeType>().ok())
1077 .unwrap_or_default()
1078 }
1079
1080 /// Retrieves the body content of the request as a UTF-8 encoded string.
1081 ///
1082 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
1083 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
1084 ///
1085 /// # Returns
1086 ///
1087 /// - `String` - The body content as a string.
1088 #[inline(always)]
1089 pub fn get_body_string(&self) -> String {
1090 String::from_utf8_lossy(self.get_body()).into_owned()
1091 }
1092
1093 /// Deserializes the body content of the request as_ref a specified type `T`.
1094 ///
1095 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1096 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1097 ///
1098 /// # Arguments
1099 ///
1100 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1101 ///
1102 /// # Returns
1103 ///
1104 /// - `Result<T, serde_json::Error>` - The deserialization result.
1105 #[inline(always)]
1106 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1107 where
1108 T: DeserializeOwned,
1109 {
1110 serde_json::from_slice(self.get_body())
1111 }
1112
1113 /// Deserializes the body content of the request as_ref a specified type `T`.
1114 ///
1115 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1116 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1117 ///
1118 /// # Arguments
1119 ///
1120 /// - `DeserializeOwned` - The target type to deserialize as_ref (must implement DeserializeOwned).
1121 ///
1122 /// # Returns
1123 ///
1124 /// - `T` - The deserialized body content.
1125 ///
1126 /// # Panics
1127 ///
1128 /// This function will panic if the deserialization fails.
1129 #[inline(always)]
1130 pub fn get_body_json<T>(&self) -> T
1131 where
1132 T: DeserializeOwned,
1133 {
1134 self.try_get_body_json().unwrap()
1135 }
1136
1137 /// Checks whether the request method is GET.
1138 ///
1139 /// # Returns
1140 ///
1141 /// - `bool` - Whether the method is GET.
1142 #[inline(always)]
1143 pub fn is_get_method(&self) -> bool {
1144 self.get_method().is_get()
1145 }
1146
1147 /// Checks whether the request method is POST.
1148 ///
1149 /// # Returns
1150 ///
1151 /// - `bool` - Whether the method is POST.
1152 #[inline(always)]
1153 pub fn is_post_method(&self) -> bool {
1154 self.get_method().is_post()
1155 }
1156
1157 /// Checks whether the request method is PUT.
1158 ///
1159 /// # Returns
1160 ///
1161 /// - `bool` - Whether the method is PUT.
1162 #[inline(always)]
1163 pub fn is_put_method(&self) -> bool {
1164 self.get_method().is_put()
1165 }
1166
1167 /// Checks whether the request method is DELETE.
1168 ///
1169 /// # Returns
1170 ///
1171 /// - `bool` - Whether the method is DELETE.
1172 #[inline(always)]
1173 pub fn is_delete_method(&self) -> bool {
1174 self.get_method().is_delete()
1175 }
1176
1177 /// Checks whether the request method is PATCH.
1178 ///
1179 /// # Returns
1180 ///
1181 /// - `bool` - Whether the method is PATCH.
1182 #[inline(always)]
1183 pub fn is_patch_method(&self) -> bool {
1184 self.get_method().is_patch()
1185 }
1186
1187 /// Checks whether the request method is HEAD.
1188 ///
1189 /// # Returns
1190 ///
1191 /// - `bool` - Whether the method is HEAD.
1192 #[inline(always)]
1193 pub fn is_head_method(&self) -> bool {
1194 self.get_method().is_head()
1195 }
1196
1197 /// Checks whether the request method is OPTIONS.
1198 ///
1199 /// # Returns
1200 ///
1201 /// - `bool` - Whether the method is OPTIONS.
1202 #[inline(always)]
1203 pub fn is_options_method(&self) -> bool {
1204 self.get_method().is_options()
1205 }
1206
1207 /// Checks whether the request method is CONNECT.
1208 ///
1209 /// # Returns
1210 ///
1211 /// - `bool` - Whether the method is CONNECT.
1212 #[inline(always)]
1213 pub fn is_connect_method(&self) -> bool {
1214 self.get_method().is_connect()
1215 }
1216
1217 /// Checks whether the request method is TRACE.
1218 ///
1219 /// # Returns
1220 ///
1221 /// - `bool` - Whether the method is TRACE.
1222 #[inline(always)]
1223 pub fn is_trace_method(&self) -> bool {
1224 self.get_method().is_trace()
1225 }
1226
1227 /// Checks whether the request method is UNKNOWN.
1228 ///
1229 /// # Returns
1230 ///
1231 /// - `bool` - Whether the method is UNKNOWN.
1232 #[inline(always)]
1233 pub fn is_unknown_method(&self) -> bool {
1234 self.get_method().is_unknown()
1235 }
1236
1237 /// Checks whether the HTTP version is HTTP/0.9.
1238 ///
1239 /// # Returns
1240 ///
1241 /// - `bool` - Whether the version is HTTP/0.9.
1242 #[inline(always)]
1243 pub fn is_http0_9_version(&self) -> bool {
1244 self.get_version().is_http0_9()
1245 }
1246
1247 /// Checks whether the HTTP version is HTTP/1.0.
1248 ///
1249 /// # Returns
1250 ///
1251 /// - `bool` - Whether the version is HTTP/1.0.
1252 #[inline(always)]
1253 pub fn is_http1_0_version(&self) -> bool {
1254 self.get_version().is_http1_0()
1255 }
1256
1257 /// Checks whether the HTTP version is HTTP/1.1.
1258 ///
1259 /// # Returns
1260 ///
1261 /// - `bool` - Whether the version is HTTP/1.1.
1262 #[inline(always)]
1263 pub fn is_http1_1_version(&self) -> bool {
1264 self.get_version().is_http1_1()
1265 }
1266
1267 /// Checks whether the HTTP version is HTTP/2.
1268 ///
1269 /// # Returns
1270 ///
1271 /// - `bool` - Whether the version is HTTP/2.
1272 #[inline(always)]
1273 pub fn is_http2_version(&self) -> bool {
1274 self.get_version().is_http2()
1275 }
1276
1277 /// Checks whether the HTTP version is HTTP/3.
1278 ///
1279 /// # Returns
1280 ///
1281 /// - `bool` - Whether the version is HTTP/3.
1282 #[inline(always)]
1283 pub fn is_http3_version(&self) -> bool {
1284 self.get_version().is_http3()
1285 }
1286
1287 /// Checks if the HTTP version is HTTP/1.1 or higher.
1288 ///
1289 /// # Returns
1290 ///
1291 /// - `bool` - Whether the version is HTTP/1.1 or higher.
1292 #[inline(always)]
1293 pub fn is_http1_1_or_higher_version(&self) -> bool {
1294 self.get_version().is_http1_1_or_higher()
1295 }
1296
1297 /// Checks whether the version belongs to the HTTP family.
1298 ///
1299 /// # Returns
1300 ///
1301 /// - `bool` - Whether the version is HTTP.
1302 #[inline(always)]
1303 pub fn is_http_version(&self) -> bool {
1304 self.get_version().is_http()
1305 }
1306
1307 /// Checks whether the HTTP version is unknown.
1308 ///
1309 /// # Returns
1310 ///
1311 /// - `bool` - Whether the version is unknown.
1312 #[inline(always)]
1313 pub fn is_unknown_version(&self) -> bool {
1314 self.get_version().is_unknown()
1315 }
1316
1317 /// Checks whether the WebSocket upgrade is enabled for this request.
1318 ///
1319 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1320 ///
1321 /// # Returns
1322 ///
1323 /// - `bool` - Whether WebSocket upgrade is enabled.
1324 #[inline(always)]
1325 pub fn is_ws_upgrade_type(&self) -> bool {
1326 self.get_upgrade_type().is_ws()
1327 }
1328
1329 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1330 ///
1331 /// # Returns
1332 ///
1333 /// - `bool` - Whether the upgrade type is h2c.
1334 #[inline(always)]
1335 pub fn is_h2c_upgrade_type(&self) -> bool {
1336 self.get_upgrade_type().is_h2c()
1337 }
1338
1339 /// Checks if the current upgrade type is TLS (any version).
1340 ///
1341 /// # Returns
1342 ///
1343 /// - `bool` - Whether the upgrade type is TLS.
1344 #[inline(always)]
1345 pub fn is_tls_upgrade_type(&self) -> bool {
1346 self.get_upgrade_type().is_tls()
1347 }
1348
1349 /// Checks whether the upgrade type is unknown.
1350 ///
1351 /// # Returns
1352 ///
1353 /// - `bool` - Whether the upgrade type is unknown.
1354 #[inline(always)]
1355 pub fn is_unknown_upgrade_type(&self) -> bool {
1356 self.get_upgrade_type().is_unknown()
1357 }
1358
1359 /// Determines if a keep-alive connection should be enabled for this request.
1360 ///
1361 /// This function checks the `Connection` header and the HTTP version to determine
1362 /// if keep-alive should be enabled. The logic is as follows:
1363 ///
1364 /// 1. If the `Connection` header exists:
1365 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1366 /// - Returns `false` if the header value is "close" (case-insensitive).
1367 /// 2. If no `Connection` header is present:
1368 /// - Returns `true` if the HTTP version is 1.1 or higher.
1369 /// - Returns `false` otherwise.
1370 ///
1371 /// # Returns
1372 ///
1373 /// - `bool` - Whether keep-alive should be enabled.
1374 #[inline(always)]
1375 pub fn is_enable_keep_alive(&self) -> bool {
1376 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1377 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1378 return true;
1379 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1380 return self.is_ws_upgrade_type();
1381 }
1382 }
1383 self.is_http1_1_or_higher_version() || self.is_ws_upgrade_type()
1384 }
1385
1386 /// Determines if keep-alive should be disabled for this request.
1387 ///
1388 /// # Returns
1389 ///
1390 /// - `bool` - Whether keep-alive should be disabled.
1391 #[inline(always)]
1392 pub fn is_disable_keep_alive(&self) -> bool {
1393 !self.is_enable_keep_alive()
1394 }
1395}