http_type/request/impl.rs
1use super::*;
2
3/// Implements the `std::error::Error` trait for `RequestError`.
4impl 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<io::Error> for RequestError {
22 /// Converts an I/O error to a `RequestError`.
23 ///
24 /// # Arguments
25 ///
26 /// - `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: 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::ServerClosedConnection(status) => *status,
122 Self::IncompleteWebSocketFrame(status) => *status,
123 Self::RequestTooLong(status) => *status,
124 Self::PathTooLong(status) => *status,
125 Self::QueryTooLong(status) => *status,
126 Self::HeaderLineTooLong(status) => *status,
127 Self::TooManyHeaders(status) => *status,
128 Self::HeaderKeyTooLong(status) => *status,
129 Self::HeaderValueTooLong(status) => *status,
130 Self::ContentLengthTooLarge(status) => *status,
131 Self::InvalidContentLength(status) => *status,
132 Self::InvalidUrlScheme(status) => *status,
133 Self::InvalidUrlHost(status) => *status,
134 Self::InvalidUrlPort(status) => *status,
135 Self::InvalidUrlPath(status) => *status,
136 Self::InvalidUrlQuery(status) => *status,
137 Self::InvalidUrlFragment(status) => *status,
138 Self::ReadTimeout(status) => *status,
139 Self::WriteTimeout(status) => *status,
140 Self::TcpConnectionFailed(status) => *status,
141 Self::TlsHandshakeFailed(status) => *status,
142 Self::TlsCertificateInvalid(status) => *status,
143 Self::WebSocketFrameTooLarge(status) => *status,
144 Self::WebSocketOpcodeUnsupported(status) => *status,
145 Self::WebSocketMaskMissing(status) => *status,
146 Self::WebSocketPayloadCorrupted(status) => *status,
147 Self::WebSocketInvalidUtf8(status) => *status,
148 Self::WebSocketInvalidCloseCode(status) => *status,
149 Self::WebSocketInvalidExtension(status) => *status,
150 Self::HttpRequestPartsInsufficient(status) => *status,
151 Self::TcpStreamConnect(status) => *status,
152 Self::TlsConnectorBuild(status) => *status,
153 Self::InvalidUrl(status) => *status,
154 Self::ConfigReadError(status) => *status,
155 Self::TcpStreamConnectString(status) => *status,
156 Self::TlsConnectorBuildString(status) => *status,
157 Self::Request(_) => HttpStatus::BadRequest,
158 Self::Unknown(status) => *status,
159 }
160 }
161
162 /// Gets the numeric HTTP status code associated with this error.
163 ///
164 /// Returns the numeric status code (e.g., 400, 404, 500) that corresponds to this error.
165 ///
166 /// # Returns
167 ///
168 /// - `ResponseStatusCode` - The numeric HTTP status code.
169 pub fn get_http_status_code(&self) -> ResponseStatusCode {
170 self.get_http_status().code()
171 }
172}
173
174/// Implementation of `Default` trait for `RequestConfig`.
175impl Default for RequestConfig {
176 /// Creates a new `RequestConfig` with default secure settings.
177 ///
178 /// This constructor initializes the configuration with standard security limits
179 /// suitable for most HTTP request parsing scenarios.
180 ///
181 /// # Returns
182 ///
183 /// - `Self` - A new `RequestConfig` instance with default settings.
184 #[inline(always)]
185 fn default() -> Self {
186 Self {
187 buffer_size: DEFAULT_BUFFER_SIZE,
188 max_path_size: DEFAULT_MAX_PATH_SIZE,
189 max_header_count: DEFAULT_MAX_HEADER_COUNT,
190 max_header_key_size: DEFAULT_MAX_HEADER_KEY_SIZE,
191 max_header_value_size: DEFAULT_MAX_HEADER_VALUE_SIZE,
192 max_body_size: DEFAULT_MAX_BODY_SIZE,
193 read_timeout_ms: DEFAULT_READ_TIMEOUT_MS,
194 }
195 }
196}
197
198impl RequestConfig {
199 /// Creates a new `RequestConfig` from a JSON string.
200 ///
201 /// # Arguments
202 ///
203 /// - `C` - The configuration, which requires the `AsRef<str>` bound.
204 ///
205 /// # Returns
206 ///
207 /// - `Result<RequestConfig, serde_json::Error>` - The parsed `RequestConfig` or an error.
208 pub fn from_json<C>(json: C) -> Result<RequestConfig, serde_json::Error>
209 where
210 C: AsRef<str>,
211 {
212 serde_json::from_str(json.as_ref())
213 }
214
215 /// Creates a new `RequestConfig` with low-security settings.
216 ///
217 /// This constructor initializes the configuration with less restrictive limits
218 /// for environments where higher limits are needed.
219 ///
220 /// # Returns
221 ///
222 /// - `Self` - A new `RequestConfig` instance with low-security settings.
223 #[inline(always)]
224 pub fn low_security() -> Self {
225 Self {
226 buffer_size: DEFAULT_LOW_SECURITY_BUFFER_SIZE,
227 max_path_size: DEFAULT_LOW_SECURITY_MAX_PATH_SIZE,
228 max_header_count: DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT,
229 max_header_key_size: DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE,
230 max_header_value_size: DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE,
231 max_body_size: DEFAULT_LOW_SECURITY_MAX_BODY_SIZE,
232 read_timeout_ms: DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS,
233 }
234 }
235
236 /// Creates a new `RequestConfig` with high-security settings.
237 ///
238 /// This constructor initializes the configuration with more restrictive limits
239 /// to provide maximum protection against various attacks in high-risk environments.
240 ///
241 /// # Returns
242 ///
243 /// - `Self` - A new `RequestConfig` instance with high-security settings.
244 #[inline(always)]
245 pub fn high_security() -> Self {
246 Self {
247 buffer_size: DEFAULT_HIGH_SECURITY_BUFFER_SIZE,
248 max_path_size: DEFAULT_HIGH_SECURITY_MAX_PATH_SIZE,
249 max_header_count: DEFAULT_HIGH_SECURITY_MAX_HEADER_COUNT,
250 max_header_key_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_KEY_SIZE,
251 max_header_value_size: DEFAULT_HIGH_SECURITY_MAX_HEADER_VALUE_SIZE,
252 max_body_size: DEFAULT_HIGH_SECURITY_MAX_BODY_SIZE,
253 read_timeout_ms: DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS,
254 }
255 }
256}
257
258/// Provides a default value for `Request`.
259///
260/// Returns a new `Request` instance with all fields initialized to their default values.
261impl Default for Request {
262 /// Builds the default `Request` with all fields set to their defaults.
263 #[inline(always)]
264 fn default() -> Self {
265 Self {
266 method: Method::default(),
267 host: String::new(),
268 version: HttpVersion::default(),
269 path: String::new(),
270 querys: hash_map_xx_hash3_64(),
271 headers: hash_map_xx_hash3_64(),
272 body: Vec::new(),
273 }
274 }
275}
276
277impl Request {
278 /// Resets the request to its default state while retaining allocated capacity.
279 ///
280 /// This keeps the header map, query map, body, and string allocations so
281 /// persistent (keep-alive) connections avoid repeated allocation per request.
282 ///
283 /// # Returns
284 ///
285 /// - `&mut Self` - A mutable reference to self for chaining.
286 pub fn reset(&mut self) -> &mut Self {
287 self.set_method(Method::default());
288 self.get_mut_host().clear();
289 self.set_version(HttpVersion::default());
290 self.get_mut_path().clear();
291 self.get_mut_querys().clear();
292 self.recycle_headers();
293 self.get_mut_body().clear();
294 self
295 }
296
297 /// Hands the header entries to the pool and empties the header map.
298 ///
299 /// The map ends up empty, exactly as clearing it would, but the name and
300 /// the value buffers of every header survive in the pool. The next
301 /// request on the same connection takes them back and overwrites them,
302 /// so a connection that keeps its headers stops allocating for them.
303 ///
304 /// # Returns
305 ///
306 /// - `()` - The headers have been recycled.
307 fn recycle_headers(&mut self) {
308 let headers: &mut RequestHeaders = self.get_mut_headers();
309 if headers.is_empty() {
310 return;
311 }
312 for (key, values) in headers.drain() {
313 return_header_entry((key, values));
314 }
315 }
316
317 /// Parses the first line of HTTP request into method, path, and version components.
318 ///
319 /// # Arguments
320 ///
321 /// - `&str` - The first line string of HTTP request to parse.
322 ///
323 /// # Returns
324 ///
325 /// - `Result<(RequestMethod, &str, RequestVersion), RequestError>` - A tuple containing:
326 /// - The parsed HTTP method
327 /// - The full path string
328 /// - The parsed HTTP version
329 /// - Or an error if parsing fails
330 #[inline(always)]
331 pub(crate) fn get_http_first_line(
332 line: &str,
333 ) -> Result<(RequestMethod, &str, RequestVersion), RequestError> {
334 let mut parts: SplitWhitespace<'_> = line.split_whitespace();
335 let method_str: &str = parts
336 .next()
337 .ok_or(RequestError::HttpRequestPartsInsufficient(
338 HttpStatus::BadRequest,
339 ))?;
340 let full_path: &str = parts
341 .next()
342 .ok_or(RequestError::HttpRequestPartsInsufficient(
343 HttpStatus::BadRequest,
344 ))?;
345 let version_str: &str = parts
346 .next()
347 .ok_or(RequestError::HttpRequestPartsInsufficient(
348 HttpStatus::BadRequest,
349 ))?;
350 let method: RequestMethod = method_str
351 .parse::<RequestMethod>()
352 .unwrap_or(Method::Unknown(method_str.to_string()));
353 let version: RequestVersion = version_str
354 .parse::<RequestVersion>()
355 .unwrap_or(RequestVersion::Unknown(version_str.to_string()));
356 Ok((method, full_path, version))
357 }
358
359 /// Validates the path length against the maximum allowed size.
360 ///
361 /// # Arguments
362 ///
363 /// - `&str` - The path string to check.
364 /// - `usize` - The maximum allowed path size.
365 ///
366 /// # Returns
367 ///
368 /// - `Result<(), RequestError>` - Ok if valid, or an error if the path is too long.
369 #[inline(always)]
370 pub(crate) fn check_http_path_size(path: &str, max_size: usize) -> Result<(), RequestError> {
371 if path.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_PATH_SIZE {
372 return Err(RequestError::PathTooLong(HttpStatus::URITooLong));
373 }
374 Ok(())
375 }
376
377 /// Parses the query string from the full path.
378 ///
379 /// Handles both query parameters (after `?`) and hash fragments (after `#`),
380 /// ensuring proper parsing when both are present.
381 ///
382 /// # Arguments
383 ///
384 /// - `&str` - The full path string containing the query.
385 /// - `Option<usize>` - The index of the query separator (`?`), if present.
386 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
387 ///
388 /// # Returns
389 ///
390 /// - `&str` - The parsed query string slice, or empty string if no query.
391 #[inline(always)]
392 pub(crate) fn get_http_query(
393 path: &str,
394 query_index: Option<usize>,
395 hash_index: Option<usize>,
396 ) -> &str {
397 query_index.map_or(EMPTY_STR, |query_index: usize| {
398 let temp: &str = &path[query_index + 1..];
399 match hash_index {
400 None => temp,
401 Some(hash_index) if hash_index <= query_index => temp,
402 Some(hash_index) => &temp[..hash_index - query_index - 1],
403 }
404 })
405 }
406
407 /// Parses the request path without query string or hash fragment.
408 ///
409 /// # Arguments
410 ///
411 /// - `&str` - The full path string.
412 /// - `Option<usize>` - The index of the query separator (`?`), if present.
413 /// - `Option<usize>` - The index of the hash separator (`#`), if present.
414 ///
415 /// # Returns
416 ///
417 /// - `&str` - The request path slice without query or hash.
418 #[inline(always)]
419 pub(crate) fn get_http_path(
420 path: &str,
421 query_index: Option<usize>,
422 hash_index: Option<usize>,
423 ) -> &str {
424 match query_index.or(hash_index) {
425 Some(separator_index) => &path[..separator_index],
426 None => path,
427 }
428 }
429
430 /// Parses a query string as_ref key-value pairs into the given map.
431 ///
432 /// Expects format "key1=value1&key2=value2". Empty values are allowed, and a
433 /// key that repeats keeps every value instead of letting the last one win.
434 /// The target map is expected to be empty; entries are inserted without
435 /// reallocating the map when it already has sufficient capacity.
436 ///
437 /// # Arguments
438 ///
439 /// - `&str` - The query string to parse.
440 /// - `&mut RequestQuerys` - The map to insert parsed parameters into.
441 #[inline(always)]
442 pub(crate) fn fill_http_querys(query: &str, querys: &mut RequestQuerys) {
443 if query.is_empty() {
444 return;
445 }
446 for pair in query.split(AND) {
447 if let Some((key, value)) = pair.split_once(EQUAL) {
448 if !key.is_empty() {
449 querys
450 .entry(key.to_string())
451 .or_default()
452 .push_back(value.to_string());
453 }
454 } else if !pair.is_empty() {
455 querys.entry(pair.to_string()).or_default();
456 }
457 }
458 }
459
460 /// Checks if the header count exceeds the maximum allowed.
461 ///
462 /// # Arguments
463 ///
464 /// - `usize` - The current number of headers parsed.
465 /// - `usize` - The maximum allowed number of headers.
466 ///
467 /// # Returns
468 ///
469 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
470 #[inline(always)]
471 pub(crate) fn check_http_header_count(
472 count: usize,
473 max_count: usize,
474 ) -> Result<(), RequestError> {
475 if count > max_count && max_count != DEFAULT_LOW_SECURITY_MAX_HEADER_COUNT {
476 return Err(RequestError::TooManyHeaders(
477 HttpStatus::RequestHeaderFieldsTooLarge,
478 ));
479 }
480 Ok(())
481 }
482
483 /// Checks if a header key exceeds the maximum allowed length.
484 ///
485 /// # Arguments
486 ///
487 /// - `&str` - The header key to check.
488 /// - `usize` - The maximum allowed length for a header key.
489 ///
490 /// # Returns
491 ///
492 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
493 #[inline(always)]
494 pub(crate) fn check_http_header_key_size(
495 key: &str,
496 max_size: usize,
497 ) -> Result<(), RequestError> {
498 if key.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_KEY_SIZE {
499 return Err(RequestError::HeaderKeyTooLong(
500 HttpStatus::RequestHeaderFieldsTooLarge,
501 ));
502 }
503 Ok(())
504 }
505
506 /// Checks if a header value exceeds the maximum allowed length.
507 ///
508 /// # Arguments
509 ///
510 /// - `&str` - The header value to check.
511 /// - `usize` - The maximum allowed length for a header value.
512 ///
513 /// # Returns
514 ///
515 /// - `Result<(), RequestError>` - Returns an error if the limit is exceeded and not in low security mode.
516 #[inline(always)]
517 pub(crate) fn check_http_header_value_size(
518 value: &str,
519 max_size: usize,
520 ) -> Result<(), RequestError> {
521 if value.len() > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_HEADER_VALUE_SIZE {
522 return Err(RequestError::HeaderValueTooLong(
523 HttpStatus::RequestHeaderFieldsTooLarge,
524 ));
525 }
526 Ok(())
527 }
528
529 /// Parses the Content-Length header value and checks it against max body size.
530 ///
531 /// # Arguments
532 ///
533 /// - `&str` - The Content-Length header value string.
534 /// - `usize` - The maximum allowed body size.
535 ///
536 /// # Returns
537 ///
538 /// - `Result<usize, RequestError>` - The parsed content length or an error.
539 #[inline(always)]
540 pub(crate) fn check_http_body_size(
541 value: &str,
542 max_size: usize,
543 ) -> Result<usize, RequestError> {
544 let length: usize = value.parse::<usize>()?;
545 if length > max_size && max_size != DEFAULT_LOW_SECURITY_MAX_BODY_SIZE {
546 return Err(RequestError::ContentLengthTooLarge(
547 HttpStatus::PayloadTooLarge,
548 ));
549 }
550 Ok(length)
551 }
552
553 /// Parses HTTP headers from a buffered reader into this request.
554 ///
555 /// This method reads header lines from the provided buffered reader until an empty line
556 /// is encountered, which indicates the end of headers. It checks header count, length,
557 /// and content according to the provided configuration. The request's headers map and
558 /// host string are expected to be empty; they are filled without reallocating when they
559 /// already have sufficient capacity.
560 ///
561 /// The line buffer belongs to the caller so that a keep-alive connection
562 /// reads every header line of every request into the same allocation.
563 ///
564 /// # Arguments
565 ///
566 /// - `&mut R` - A mutable reference to a buffered reader, which requires the
567 /// `AsyncBufReadExt + Unpin` bound.
568 /// - `&RequestConfig` - Configuration for security limits and buffer settings.
569 /// - `&mut String` - The buffer the header lines are read into.
570 ///
571 /// # Returns
572 ///
573 /// - `Result<usize, RequestError>` - The content length parsed from the
574 /// Content-Length header, or an error if parsing fails.
575 pub(crate) async fn get_http_headers<R>(
576 &mut self,
577 reader: &mut R,
578 config: &RequestConfig,
579 header_line_buffer: &mut String,
580 ) -> Result<usize, RequestError>
581 where
582 R: AsyncBufReadExt + Unpin,
583 {
584 let Request { headers, host, .. } = self;
585 let max_header_count: usize = config.get_max_header_count();
586 let max_header_key_size: usize = config.get_max_header_key_size();
587 let max_header_value_size: usize = config.get_max_header_value_size();
588 let max_body_size: usize = config.get_max_body_size();
589 let mut content_size: usize = 0;
590 let mut header_count: usize = 0;
591 loop {
592 header_line_buffer.clear();
593 AsyncBufReadExt::read_line(reader, header_line_buffer).await?;
594 let header_line: &str = header_line_buffer.trim();
595 if header_line.is_empty() {
596 break;
597 }
598 header_count += 1;
599 Self::check_http_header_count(header_count, max_header_count)?;
600 let (key_part, value_part): (&str, &str) = match header_line.split_once(COLON) {
601 Some(parts) => parts,
602 None => continue,
603 };
604 let key_trimmed: &str = key_part.trim();
605 if key_trimmed.is_empty() {
606 continue;
607 }
608 Self::check_http_header_key_size(key_trimmed, max_header_key_size)?;
609 let value: &str = value_part.trim();
610 Self::check_http_header_value_size(value, max_header_value_size)?;
611 match key_trimmed {
612 key if key.eq_ignore_ascii_case(HOST) => {
613 host.clear();
614 host.push_str(value);
615 }
616 key if key.eq_ignore_ascii_case(CONTENT_LENGTH) => {
617 content_size = Self::check_http_body_size(value, max_body_size)?;
618 }
619 _ => {}
620 }
621 Self::insert_http_header(headers, key_trimmed, value);
622 }
623 Ok(content_size)
624 }
625
626 /// Stores one header, reusing a pooled name and value where possible.
627 ///
628 /// The name is lowercased into the buffer of a recycled entry and the
629 /// value is written into that entry's value buffer, so a header that was
630 /// already seen on this connection costs no allocation at all.
631 ///
632 /// # Arguments
633 ///
634 /// - `&mut RequestHeaders` - The header map to store the header in.
635 /// - `&str` - The header name, as it arrived.
636 /// - `&str` - The header value.
637 fn insert_http_header(headers: &mut RequestHeaders, key: &str, value: &str) {
638 let (mut name, mut values): (String, VecDeque<String>) =
639 take_header_entry().unwrap_or_else(|| (String::new(), VecDeque::new()));
640 name.clear();
641 name.push_str(key);
642 name.make_ascii_lowercase();
643 match headers.entry(name) {
644 Entry::Occupied(mut occupied) => {
645 // The header repeats: it keeps every value it was given.
646 occupied.get_mut().push_back(value.to_string());
647 return_header_entry((String::new(), values));
648 }
649 Entry::Vacant(vacant) => {
650 // A recycled entry may carry the values of a header that was
651 // sent more than once. Those values belong to that header, so
652 // only the first one is kept and the rest are dropped.
653 while values.len() > 1 {
654 values.pop_back();
655 }
656 if values.is_empty() {
657 values.push_back(String::new());
658 }
659 if let Some(slot) = values.front_mut() {
660 slot.clear();
661 slot.push_str(value);
662 }
663 vacant.insert(values);
664 }
665 }
666 }
667
668 /// Reads the request body from the buffered reader into the given buffer.
669 ///
670 /// The target buffer is cleared and resized to the expected content size,
671 /// retaining its allocation when it already has sufficient capacity.
672 ///
673 /// # Arguments
674 ///
675 /// - `&mut R` - The buffered reader to read from, which requires the `AsyncRead + Unpin` bound.
676 /// - `&mut RequestBody` - The buffer to read the body bytes into.
677 /// - `usize` - The expected content size.
678 ///
679 /// # Returns
680 ///
681 /// - `Result<(), RequestError>` - Ok on success, or an error if reading fails.
682 #[inline(always)]
683 pub(crate) async fn fill_http_body<R>(
684 reader: &mut R,
685 body: &mut RequestBody,
686 content_size: usize,
687 ) -> Result<(), RequestError>
688 where
689 R: AsyncRead + Unpin,
690 {
691 body.clear();
692 if content_size > 0 {
693 body.resize(content_size, 0);
694 AsyncReadExt::read_exact(reader, body).await?;
695 }
696 Ok(())
697 }
698
699 /// Tries to get a query parameter by key.
700 ///
701 /// The key type must implement AsRef<str> conversion. A key that repeats in
702 /// the query carries every one of its values.
703 ///
704 /// # Arguments
705 ///
706 /// - `K` - The query parameter key, which implements `AsRef<str>`.
707 ///
708 /// # Returns
709 ///
710 /// - `Option<RequestQuerysValue>` - Every value of the parameter if it exists.
711 #[inline(always)]
712 pub fn try_get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
713 where
714 K: AsRef<str>,
715 {
716 self.get_querys().get(key.as_ref()).cloned()
717 }
718
719 /// Tries to get the first query parameter value by key.
720 ///
721 /// Use this when the parameter is expected to appear once; use
722 /// `try_get_query` when every value matters.
723 ///
724 /// # Arguments
725 ///
726 /// - `K` - The query parameter key, which implements `AsRef<str>`.
727 ///
728 /// # Returns
729 ///
730 /// - `Option<RequestQuerysValueItem>` - The first parameter value if it exists.
731 #[inline(always)]
732 pub fn try_get_query_front<K>(&self, key: K) -> Option<RequestQuerysValueItem>
733 where
734 K: AsRef<str>,
735 {
736 self.get_querys()
737 .get(key.as_ref())
738 .and_then(|values: &VecDeque<String>| values.front().cloned())
739 }
740
741 /// Tries to get the last query parameter value by key.
742 ///
743 /// # Arguments
744 ///
745 /// - `K` - The query parameter key, which implements `AsRef<str>`.
746 ///
747 /// # Returns
748 ///
749 /// - `Option<RequestQuerysValueItem>` - The last parameter value if it exists.
750 #[inline(always)]
751 pub fn try_get_query_back<K>(&self, key: K) -> Option<RequestQuerysValueItem>
752 where
753 K: AsRef<str>,
754 {
755 self.get_querys()
756 .get(key.as_ref())
757 .and_then(|values: &VecDeque<String>| values.back().cloned())
758 }
759
760 /// Tries to get the number of values of a query parameter.
761 ///
762 /// # Arguments
763 ///
764 /// - `K` - The query parameter key, which implements `AsRef<str>`.
765 ///
766 /// # Returns
767 ///
768 /// - `Option<usize>` - The number of values if the parameter exists.
769 #[inline(always)]
770 pub fn try_get_query_size<K>(&self, key: K) -> Option<usize>
771 where
772 K: AsRef<str>,
773 {
774 self.get_querys()
775 .get(key.as_ref())
776 .map(|values: &VecDeque<String>| values.len())
777 }
778
779 /// Checks whether a query parameter exists.
780 ///
781 /// # Arguments
782 ///
783 /// - `K` - The query parameter key, which implements `AsRef<str>`.
784 ///
785 /// # Returns
786 ///
787 /// - `bool` - Whether the parameter exists.
788 #[inline(always)]
789 pub fn has_query<K>(&self, key: K) -> bool
790 where
791 K: AsRef<str>,
792 {
793 self.get_querys().contains_key(key.as_ref())
794 }
795
796 /// Gets a query parameter by key.
797 ///
798 /// # Arguments
799 ///
800 /// - `K` - The query parameter key, which implements `AsRef<str>`.
801 ///
802 /// # Returns
803 ///
804 /// - `RequestQuerysValue` - Every value of the parameter.
805 ///
806 /// # Panics
807 ///
808 /// This function will panic if the query parameter key is not found.
809 #[inline(always)]
810 pub fn get_query<K>(&self, key: K) -> RequestQuerysValue
811 where
812 K: AsRef<str>,
813 {
814 self.try_get_query(key).unwrap()
815 }
816
817 /// Gets the first query parameter value by key.
818 ///
819 /// # Arguments
820 ///
821 /// - `K` - The query parameter key, which implements `AsRef<str>`.
822 ///
823 /// # Returns
824 ///
825 /// - `RequestQuerysValueItem` - The first parameter value.
826 ///
827 /// # Panics
828 ///
829 /// This function will panic if the query parameter key is not found.
830 #[inline(always)]
831 pub fn get_query_front<K>(&self, key: K) -> RequestQuerysValueItem
832 where
833 K: AsRef<str>,
834 {
835 self.try_get_query_front(key).unwrap()
836 }
837
838 /// Retrieves the number of query parameters.
839 ///
840 /// # Returns
841 ///
842 /// - `usize` - The count of distinct query parameter keys.
843 #[inline(always)]
844 pub fn get_querys_size(&self) -> usize {
845 self.get_querys().len()
846 }
847
848 /// Tries to retrieve the value of a request header by its key.
849 ///
850 /// The key is matched case-insensitively, because the parser stores every
851 /// header name lowercased and an HTTP header name is case-insensitive by
852 /// specification. Looking a header up with `Content-Type` and with
853 /// `content-type` therefore find the same value.
854 ///
855 /// # Arguments
856 ///
857 /// - `K` - The header's key, which must implement `AsRef<str>`.
858 ///
859 /// # Returns
860 ///
861 /// - `Option<RequestHeadersValue>` - The optional header values.
862 #[inline(always)]
863 pub fn try_get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
864 where
865 K: AsRef<str>,
866 {
867 self.get_headers()
868 .get(&key.as_ref().to_ascii_lowercase())
869 .cloned()
870 }
871
872 /// Retrieves the value of a request header by its key.
873 ///
874 /// # Arguments
875 ///
876 /// - `K` - The header's key, which must implement `AsRef<str>`.
877 ///
878 /// # Returns
879 ///
880 /// - `RequestHeadersValue` - The optional header values.
881 ///
882 /// # Panics
883 ///
884 /// This function will panic if the header key is not found.
885 #[inline(always)]
886 pub fn get_header<K>(&self, key: K) -> RequestHeadersValue
887 where
888 K: AsRef<str>,
889 {
890 self.try_get_header(key).unwrap()
891 }
892
893 /// Tries to retrieve the first value of a request header by its key.
894 ///
895 /// # Arguments
896 ///
897 /// - `K` - The header's key, which must implement `AsRef<str>`.
898 ///
899 /// # Returns
900 ///
901 /// - `Option<RequestHeadersValueItem>` - The first header value if exists.
902 #[inline(always)]
903 pub fn try_get_header_front<K>(&self, key: K) -> Option<RequestHeadersValueItem>
904 where
905 K: AsRef<str>,
906 {
907 self.get_headers()
908 .get(&key.as_ref().to_ascii_lowercase())
909 .and_then(|header_values: &VecDeque<String>| header_values.front().cloned())
910 }
911
912 /// Retrieves the first value of a request header by its key.
913 ///
914 /// # Arguments
915 ///
916 /// - `K` - The header's key, which must implement `AsRef<str>`.
917 ///
918 /// # Returns
919 ///
920 /// - `RequestHeadersValueItem` - The first header value if exists.
921 ///
922 /// # Panics
923 ///
924 /// This function will panic if the header key is not found.
925 #[inline(always)]
926 pub fn get_header_front<K>(&self, key: K) -> RequestHeadersValueItem
927 where
928 K: AsRef<str>,
929 {
930 self.try_get_header_front(key).unwrap()
931 }
932
933 /// Tries to retrieve the last value of a request header by its key.
934 ///
935 /// # Arguments
936 ///
937 /// - `K` - The header's key, which must implement `AsRef<str>`.
938 ///
939 /// # Returns
940 ///
941 /// - `Option<RequestHeadersValueItem>` - The last header value if exists.
942 #[inline(always)]
943 pub fn try_get_header_back<K>(&self, key: K) -> Option<RequestHeadersValueItem>
944 where
945 K: AsRef<str>,
946 {
947 self.get_headers()
948 .get(&key.as_ref().to_ascii_lowercase())
949 .and_then(|header_values: &VecDeque<String>| header_values.back().cloned())
950 }
951
952 /// Retrieves the last value of a request header by its key.
953 ///
954 /// # Arguments
955 ///
956 /// - `K` - The header's key, which must implement `AsRef<str>`.
957 ///
958 /// # Returns
959 ///
960 /// - `RequestHeadersValueItem` - The last header value if exists.
961 ///
962 /// # Panics
963 ///
964 /// This function will panic if the header key is not found.
965 #[inline(always)]
966 pub fn get_header_back<K>(&self, key: K) -> RequestHeadersValueItem
967 where
968 K: AsRef<str>,
969 {
970 self.try_get_header_back(key).unwrap()
971 }
972
973 /// Tries to retrieve the number of values for a specific header.
974 ///
975 /// # Arguments
976 ///
977 /// - `K` - The header's key, which must implement `AsRef<str>`.
978 ///
979 /// # Returns
980 ///
981 /// - `Option<usize>` - The count of values for the header if exists.
982 #[inline(always)]
983 pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
984 where
985 K: AsRef<str>,
986 {
987 self.get_headers()
988 .get(&key.as_ref().to_ascii_lowercase())
989 .map(|header_values: &VecDeque<String>| header_values.len())
990 }
991
992 /// Retrieves the number of values for a specific header.
993 ///
994 /// # Arguments
995 ///
996 /// - `K` - The header's key, which must implement `AsRef<str>`.
997 ///
998 /// # Returns
999 ///
1000 /// - `usize` - The count of values for the header.
1001 ///
1002 /// # Panics
1003 ///
1004 /// This function will panic if the header key is not found.
1005 #[inline(always)]
1006 pub fn get_header_size<K>(&self, key: K) -> usize
1007 where
1008 K: AsRef<str>,
1009 {
1010 self.try_get_header_size(key).unwrap()
1011 }
1012
1013 /// Retrieves the total number of header values across all headers.
1014 ///
1015 /// # Returns
1016 ///
1017 /// - `usize` - The total count of all header values.
1018 #[inline(always)]
1019 pub fn get_headers_values_size(&self) -> usize {
1020 self.get_headers()
1021 .values()
1022 .map(|header_values: &VecDeque<String>| header_values.len())
1023 .sum()
1024 }
1025
1026 /// Retrieves the number of unique headers.
1027 ///
1028 /// # Returns
1029 ///
1030 /// - `usize` - The count of unique header keys.
1031 #[inline(always)]
1032 pub fn get_headers_size(&self) -> usize {
1033 self.get_headers().len()
1034 }
1035
1036 /// Checks if a specific header exists.
1037 ///
1038 /// # Arguments
1039 ///
1040 /// - `K` - The header key to check, which must implement `AsRef<str>`.
1041 ///
1042 /// # Returns
1043 ///
1044 /// - `bool` - Whether the header exists.
1045 #[inline(always)]
1046 pub fn has_header<K>(&self, key: K) -> bool
1047 where
1048 K: AsRef<str>,
1049 {
1050 self.get_headers()
1051 .contains_key(&key.as_ref().to_ascii_lowercase())
1052 }
1053
1054 /// Checks if a header contains a specific value.
1055 ///
1056 /// # Arguments
1057 ///
1058 /// - `K` - The header key to check, which must implement `AsRef<str>`.
1059 /// - `V` - The value to search for, which must implement `AsRef<str>`.
1060 ///
1061 /// # Returns
1062 ///
1063 /// - `bool` - Whether the header contains the value.
1064 #[inline(always)]
1065 pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
1066 where
1067 K: AsRef<str>,
1068 V: AsRef<str>,
1069 {
1070 if let Some(values) = self.get_headers().get(&key.as_ref().to_ascii_lowercase()) {
1071 values.iter().any(|data: &String| data == value.as_ref())
1072 } else {
1073 false
1074 }
1075 }
1076
1077 /// Tries to parse cookies from the `Cookie` header.
1078 ///
1079 /// This method retrieves the `Cookie` header value and parses it into
1080 /// a collection of key-value pairs representing the cookies.
1081 ///
1082 /// # Returns
1083 ///
1084 /// - `Option<Cookies>` - The parsed cookies if the header exists, otherwise `None`.
1085 #[inline(always)]
1086 pub fn try_get_cookies(&self) -> Option<Cookies> {
1087 self.try_get_header_back(COOKIE)
1088 .map(|cookie_header: String| Cookie::parse(cookie_header))
1089 }
1090
1091 /// Parses cookies from the `Cookie` header.
1092 ///
1093 /// This method retrieves the `Cookie` header value and parses it into
1094 /// a collection of key-value pairs representing the cookies.
1095 ///
1096 /// # Returns
1097 ///
1098 /// - `Cookies` - The parsed cookies.
1099 ///
1100 /// # Panics
1101 ///
1102 /// This function will panic if the `Cookie` header is not found.
1103 #[inline(always)]
1104 pub fn get_cookies(&self) -> Cookies {
1105 self.try_get_cookies().unwrap()
1106 }
1107
1108 /// Tries to get a cookie value by its key.
1109 ///
1110 /// This method first parses the cookies from the `Cookie` header,
1111 /// then attempts to retrieve the value for the specified key.
1112 ///
1113 /// # Arguments
1114 ///
1115 /// - `K` - The cookie key, which implements `AsRef<str>`.
1116 ///
1117 /// # Returns
1118 ///
1119 /// - `Option<CookieValue>` - The cookie value if exists.
1120 #[inline(always)]
1121 pub fn try_get_cookie<K>(&self, key: K) -> Option<CookieValue>
1122 where
1123 K: AsRef<str>,
1124 {
1125 self.try_get_cookies()
1126 .and_then(|cookies: Cookies| cookies.get(key.as_ref()).cloned())
1127 }
1128
1129 /// Gets a cookie value by its key.
1130 ///
1131 /// This method first parses the cookies from the `Cookie` header,
1132 /// then retrieves the value for the specified key.
1133 ///
1134 /// # Arguments
1135 ///
1136 /// - `K` - The cookie key, which implements `AsRef<str>`.
1137 ///
1138 /// # Returns
1139 ///
1140 /// - `CookieValue` - The cookie value.
1141 ///
1142 /// # Panics
1143 ///
1144 /// This function will panic if the `Cookie` header is not found
1145 /// or the cookie key does not exist.
1146 #[inline(always)]
1147 pub fn get_cookie<K>(&self, key: K) -> CookieValue
1148 where
1149 K: AsRef<str>,
1150 {
1151 self.try_get_cookie(key).unwrap()
1152 }
1153
1154 /// Retrieves the upgrade type from the request headers.
1155 ///
1156 /// This method looks for the `UPGRADE` header and attempts to parse its value
1157 /// as_ref an `UpgradeType`. If the header is missing or the value is invalid,
1158 /// it returns the default `UpgradeType`.
1159 ///
1160 /// # Returns
1161 ///
1162 /// - `UpgradeType` - The parsed upgrade type.
1163 #[inline(always)]
1164 pub fn get_upgrade_type(&self) -> UpgradeType {
1165 self.try_get_header_back(UPGRADE)
1166 .and_then(|data: String| data.parse::<UpgradeType>().ok())
1167 .unwrap_or_default()
1168 }
1169
1170 /// Retrieves the body content of the request as a UTF-8 encoded string.
1171 ///
1172 /// This method uses `String::from_utf8_lossy` to convert the byte slice returned by `self.get_body()` as a string.
1173 /// If the byte slice contains invalid UTF-8 sequences, they will be replaced with the Unicode replacement character ().
1174 ///
1175 /// # Returns
1176 ///
1177 /// - `String` - The body content as a string.
1178 #[inline(always)]
1179 pub fn get_body_string(&self) -> String {
1180 String::from_utf8_lossy(self.get_body()).into_owned()
1181 }
1182
1183 /// Deserializes the body content of the request as_ref a specified type `T`.
1184 ///
1185 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1186 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1187 ///
1188 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1189 ///
1190 /// # Returns
1191 ///
1192 /// - `Result<T, serde_json::Error>` - The deserialization result.
1193 #[inline(always)]
1194 pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
1195 where
1196 T: DeserializeOwned,
1197 {
1198 serde_json::from_slice(self.get_body())
1199 }
1200
1201 /// Deserializes the body content of the request as_ref a specified type `T`.
1202 ///
1203 /// This method first retrieves the body content as a byte slice using `self.get_body()`.
1204 /// It then attempts to deserialize the byte slice as_ref the specified type `T` using `json_from_slice`.
1205 ///
1206 /// The target type `T` is a type parameter of this method and must implement `DeserializeOwned`.
1207 ///
1208 /// # Returns
1209 ///
1210 /// - `T` - The deserialized body content.
1211 ///
1212 /// # Panics
1213 ///
1214 /// This function will panic if the deserialization fails.
1215 #[inline(always)]
1216 pub fn get_body_json<T>(&self) -> T
1217 where
1218 T: DeserializeOwned,
1219 {
1220 self.try_get_body_json().unwrap()
1221 }
1222
1223 /// Checks whether the WebSocket upgrade is enabled for this request.
1224 ///
1225 /// This method determines if the `UPGRADE` header indicates a WebSocket connection.
1226 ///
1227 /// # Returns
1228 ///
1229 /// - `bool` - Whether WebSocket upgrade is enabled.
1230 #[inline(always)]
1231 pub fn is_ws_upgrade_type(&self) -> bool {
1232 self.get_upgrade_type().is_ws()
1233 }
1234
1235 /// Checks whether the request declares a `multipart/form-data` body.
1236 ///
1237 /// # Returns
1238 ///
1239 /// - `bool` - Whether the request content type is `multipart/form-data`.
1240 #[inline(always)]
1241 pub fn is_multipart_form_data(&self) -> bool {
1242 self.try_get_content_type()
1243 .map(|content_type: String| MultipartFormData::is_form_data(content_type))
1244 .unwrap_or(false)
1245 }
1246
1247 /// Tries to get the request content type with its parameters stripped.
1248 ///
1249 /// A `Content-Type` header such as `text/html; charset=utf-8` yields the
1250 /// media type alone, so a caller comparing against a media type does not
1251 /// have to know that parameters may follow it.
1252 ///
1253 /// # Returns
1254 ///
1255 /// - `Option<RequestContentType>` - The media type, or `None` when the header is absent.
1256 #[inline(always)]
1257 pub fn try_get_content_type(&self) -> Option<RequestContentType> {
1258 self.try_get_header_front(CONTENT_TYPE)
1259 .map(|value: String| {
1260 value
1261 .split(SEMICOLON)
1262 .next()
1263 .unwrap_or(EMPTY_STR)
1264 .trim()
1265 .to_ascii_lowercase()
1266 })
1267 }
1268
1269 /// Tries to get one parameter of the request `Content-Type` header.
1270 ///
1271 /// The name is matched case-insensitively and a quoted value is unquoted,
1272 /// so both `boundary=abc` and `boundary="abc"` yield `abc`.
1273 ///
1274 /// # Arguments
1275 ///
1276 /// - `K` - The parameter name, which requires the `AsRef<str>` bound.
1277 ///
1278 /// # Returns
1279 ///
1280 /// - `Option<RequestContentTypeParameter>` - The parameter value, or `None` when absent.
1281 pub fn try_get_content_type_parameter<K>(&self, name: K) -> Option<RequestContentTypeParameter>
1282 where
1283 K: AsRef<str>,
1284 {
1285 let content_type: String = self.try_get_header_front(CONTENT_TYPE)?;
1286 let name: &str = name.as_ref();
1287 for parameter in content_type.split(SEMICOLON).skip(1) {
1288 let (key, value) = parameter.trim().split_once(EQUAL)?;
1289 if !key.trim().eq_ignore_ascii_case(name) {
1290 continue;
1291 }
1292 let value: &str = value.trim();
1293 let value: &str = value
1294 .strip_prefix(MULTIPART_PARAMETER_QUOTE)
1295 .and_then(|value: &str| value.strip_suffix(MULTIPART_PARAMETER_QUOTE))
1296 .unwrap_or(value);
1297 if !value.is_empty() {
1298 return Some(value.to_string());
1299 }
1300 }
1301 None
1302 }
1303
1304 /// Tries to decode a `multipart/form-data` body into its parts.
1305 ///
1306 /// The boundary is read from the request `Content-Type` header rather than
1307 /// guessed, so a body whose content type declares no boundary, a truncated
1308 /// body, and a part without a name all yield `None`.
1309 ///
1310 /// # Returns
1311 ///
1312 /// - `Option<MultipartFormDataParts>` - The decoded parts, or `None` when unavailable.
1313 pub fn try_get_body_form_data(&self) -> Option<MultipartFormDataParts> {
1314 let boundary: MultipartFormDataBoundary =
1315 self.try_get_content_type_parameter(MULTIPART_BOUNDARY_PARAMETER)?;
1316 MultipartFormData::parse(self.get_body(), &boundary)
1317 }
1318
1319 /// Decodes an `application/x-www-form-urlencoded` body into its fields.
1320 ///
1321 /// # Returns
1322 ///
1323 /// - `BodyForm` - The decoded form fields.
1324 #[inline(always)]
1325 pub fn get_body_form(&self) -> BodyForm {
1326 MultipartFormData::parse_url_encoded(self.get_body())
1327 }
1328
1329 /// Tries to get a plain text field of a `multipart/form-data` body.
1330 ///
1331 /// A part that uploads a file is skipped, so a file field never silently
1332 /// decodes as text.
1333 ///
1334 /// # Arguments
1335 ///
1336 /// - `K` - The form field name, which requires the `AsRef<str>` bound.
1337 ///
1338 /// # Returns
1339 ///
1340 /// - `Option<BodyFormValue>` - The field value, or `None` when absent or a file.
1341 pub fn try_get_body_form_data_text<K>(&self, name: K) -> Option<BodyFormValue>
1342 where
1343 K: AsRef<str>,
1344 {
1345 let parts: MultipartFormDataParts = self.try_get_body_form_data()?;
1346 MultipartFormData::try_get_part_text(&parts, name)
1347 }
1348
1349 /// Checks if the current upgrade type is HTTP/2 cleartext (h2c).
1350 ///
1351 /// # Returns
1352 ///
1353 /// - `bool` - Whether the upgrade type is h2c.
1354 #[inline(always)]
1355 pub fn is_h2c_upgrade_type(&self) -> bool {
1356 self.get_upgrade_type().is_h2c()
1357 }
1358
1359 /// Checks if the current upgrade type is TLS (any version).
1360 ///
1361 /// # Returns
1362 ///
1363 /// - `bool` - Whether the upgrade type is TLS.
1364 #[inline(always)]
1365 pub fn is_tls_upgrade_type(&self) -> bool {
1366 self.get_upgrade_type().is_tls()
1367 }
1368
1369 /// Checks whether the upgrade type is unknown.
1370 ///
1371 /// # Returns
1372 ///
1373 /// - `bool` - Whether the upgrade type is unknown.
1374 #[inline(always)]
1375 pub fn is_unknown_upgrade_type(&self) -> bool {
1376 self.get_upgrade_type().is_unknown()
1377 }
1378
1379 /// Determines if a keep-alive connection should be enabled for this request.
1380 ///
1381 /// This function checks the `Connection` header and the HTTP version to determine
1382 /// if keep-alive should be enabled. The logic is as follows:
1383 ///
1384 /// 1. If the `Connection` header exists:
1385 /// - Returns `true` if the header value is "keep-alive" (case-insensitive).
1386 /// - Returns `false` if the header value is "close" (case-insensitive).
1387 /// 2. If no `Connection` header is present:
1388 /// - Returns `true` if the HTTP version is 1.1 or higher.
1389 /// - Returns `false` otherwise.
1390 ///
1391 /// # Returns
1392 ///
1393 /// - `bool` - Whether keep-alive should be enabled.
1394 #[inline(always)]
1395 pub fn is_enable_keep_alive(&self) -> bool {
1396 if let Some(connection_value) = self.try_get_header_back(CONNECTION) {
1397 if connection_value.eq_ignore_ascii_case(KEEP_ALIVE) {
1398 return true;
1399 } else if connection_value.eq_ignore_ascii_case(CLOSE) {
1400 return self.is_ws_upgrade_type();
1401 }
1402 }
1403 self.get_version().is_http1_1_or_higher() || self.is_ws_upgrade_type()
1404 }
1405
1406 /// Determines if keep-alive should be disabled for this request.
1407 ///
1408 /// # Returns
1409 ///
1410 /// - `bool` - Whether keep-alive should be disabled.
1411 #[inline(always)]
1412 pub fn is_disable_keep_alive(&self) -> bool {
1413 !self.is_enable_keep_alive()
1414 }
1415}