Skip to main content

hyper/proto/h1/
role.rs

1use std::mem::MaybeUninit;
2
3#[cfg(feature = "client")]
4use std::fmt::{self, Write as _};
5
6use bytes::Bytes;
7use bytes::BytesMut;
8#[cfg(feature = "client")]
9use http::header::Entry;
10#[cfg(feature = "server")]
11use http::header::ValueIter;
12use http::header::{self, HeaderMap, HeaderName, HeaderValue};
13use http::{Method, StatusCode, Version};
14use smallvec::{smallvec, smallvec_inline, SmallVec};
15
16use crate::body::DecodedLength;
17#[cfg(feature = "server")]
18use crate::common::date;
19use crate::error::Parse;
20use crate::ext::HeaderCaseMap;
21#[cfg(feature = "ffi")]
22use crate::ext::OriginalHeaderOrder;
23use crate::headers;
24use crate::proto::h1::{
25    Encode, Encoder, Http1Transaction, ParseContext, ParseResult, ParsedMessage,
26};
27#[cfg(feature = "client")]
28use crate::proto::RequestHead;
29use crate::proto::{BodyLength, MessageHead, RequestLine};
30
31pub(crate) const DEFAULT_MAX_HEADERS: usize = 100;
32const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
33#[cfg(feature = "server")]
34const MAX_URI_LEN: usize = (u16::MAX - 1) as usize;
35
36macro_rules! header_name {
37    ($bytes:expr) => {{
38        {
39            match HeaderName::from_bytes($bytes) {
40                Ok(name) => name,
41                Err(e) => maybe_panic!(e),
42            }
43        }
44    }};
45}
46/// construct `HeaderValue` from a maybe shared expression.
47macro_rules! header_value {
48    ($bytes:expr) => {{
49        {
50            // unsafe used because of the call of `HeaderValue::from_maybe_shared_unchecked`.
51            // SAFETY:
52            // 1. The input `$bytes` must be a valid header value as per RFC 7230.
53            // 2. Specifically, it must not contain any prohibited characters (like `\r`, `\n`, or non-visible ASCII characters outside of allowed ranges).
54            // 3. This is safe because the caller is responsible for ensuring the byte content
55            //    has been validated or is known to be a constant/static valid header value.
56            unsafe { HeaderValue::from_maybe_shared_unchecked($bytes) }
57        }
58    }};
59}
60
61macro_rules! maybe_panic {
62    ($($arg:tt)*) => ({
63        let _err = ($($arg)*);
64        if cfg!(debug_assertions) {
65            panic!("{:?}", _err);
66        } else {
67            error!("Internal Hyper error, please report {:?}", _err);
68            return Err(Parse::Internal)
69        }
70    })
71}
72
73pub(super) fn parse_headers<T>(
74    bytes: &mut BytesMut,
75    prev_len: Option<usize>,
76    ctx: ParseContext<'_>,
77) -> ParseResult<T::Incoming>
78where
79    T: Http1Transaction,
80{
81    // If the buffer is empty, don't bother entering the span, it's just noise.
82    if bytes.is_empty() {
83        return Ok(None);
84    }
85
86    let _entered = trace_span!("parse_headers");
87
88    if let Some(prev_len) = prev_len {
89        if !is_complete_fast(bytes, prev_len) {
90            return Ok(None);
91        }
92    }
93
94    T::parse(bytes, ctx)
95}
96
97/// A fast scan for the end of a message.
98/// Used when there was a partial read, to skip full parsing on a
99/// a slow connection.
100fn is_complete_fast(bytes: &[u8], prev_len: usize) -> bool {
101    let start = prev_len.saturating_sub(3);
102    let bytes = &bytes[start..];
103
104    for (i, b) in bytes.iter().copied().enumerate() {
105        if b == b'\r' {
106            if bytes[i + 1..].chunks(3).next() == Some(&b"\n\r\n"[..]) {
107                return true;
108            }
109        } else if b == b'\n' && bytes.get(i + 1) == Some(&b'\n') {
110            return true;
111        }
112    }
113
114    false
115}
116
117pub(super) fn encode_headers<T>(
118    enc: Encode<'_, T::Outgoing>,
119    dst: &mut Vec<u8>,
120) -> crate::Result<Encoder>
121where
122    T: Http1Transaction,
123{
124    let _entered = trace_span!("encode_headers");
125    T::encode(enc, dst)
126}
127
128// There are 2 main roles, Client and Server.
129
130#[cfg(feature = "client")]
131pub(crate) enum Client {}
132
133#[cfg(feature = "server")]
134pub(crate) enum Server {}
135
136#[cfg(feature = "server")]
137impl Http1Transaction for Server {
138    type Incoming = RequestLine;
139    type Outgoing = StatusCode;
140    #[cfg(feature = "tracing")]
141    const LOG: &'static str = "{role=server}";
142
143    fn parse(buf: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<RequestLine> {
144        debug_assert!(!buf.is_empty(), "parse called with empty buf");
145
146        let mut keep_alive;
147        let is_http_11;
148        let subject;
149        let version;
150        let len;
151        let headers_len;
152        let method;
153        let path_range;
154
155        // Both headers_indices and headers are using uninitialized memory,
156        // but we *never* read any of it until after httparse has assigned
157        // values into it. By not zeroing out the stack memory, this saves
158        // a good ~5% on pipeline benchmarks.
159        let mut headers_indices: SmallVec<[MaybeUninit<HeaderIndices>; DEFAULT_MAX_HEADERS]> =
160            match ctx.h1_max_headers {
161                Some(cap) => smallvec![MaybeUninit::uninit(); cap],
162                None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
163            };
164        {
165            let mut headers: SmallVec<[MaybeUninit<httparse::Header<'_>>; DEFAULT_MAX_HEADERS]> =
166                match ctx.h1_max_headers {
167                    Some(cap) => smallvec![MaybeUninit::uninit(); cap],
168                    None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
169                };
170            trace!(bytes = buf.len(), "Request.parse");
171            let mut req = httparse::Request::new(&mut []);
172            let bytes = buf.as_ref();
173            match ctx.h1_parser_config.parse_request_with_uninit_headers(
174                &mut req,
175                bytes,
176                &mut headers,
177            ) {
178                Ok(httparse::Status::Complete(parsed_len)) => {
179                    trace!("Request.parse Complete({})", parsed_len);
180                    len = parsed_len;
181                    let uri = req.path.expect("httparse completed");
182                    if uri.len() > MAX_URI_LEN {
183                        return Err(Parse::UriTooLong);
184                    }
185                    method =
186                        Method::from_bytes(req.method.expect("httparse completed").as_bytes())?;
187                    path_range = Server::record_path_range(bytes, uri);
188                    version = if req.version.expect("httparse completed") == 1 {
189                        keep_alive = true;
190                        is_http_11 = true;
191                        Version::HTTP_11
192                    } else {
193                        keep_alive = false;
194                        is_http_11 = false;
195                        Version::HTTP_10
196                    };
197
198                    record_header_indices(bytes, req.headers, &mut headers_indices)?;
199                    headers_len = req.headers.len();
200                }
201                Ok(httparse::Status::Partial) => return Ok(None),
202                // if invalid Token, try to determine if for method or path
203                Err(httparse::Error::Token) => {
204                    return Err({
205                        if req.method.is_none() {
206                            Parse::Method
207                        } else {
208                            debug_assert!(req.path.is_none());
209                            Parse::Uri
210                        }
211                    })
212                }
213                Err(err) => return Err(err.into()),
214            }
215        };
216
217        let slice = buf.split_to(len).freeze();
218        let uri = {
219            let uri_bytes = slice.slice_ref(&slice[path_range]);
220            // TODO(lucab): switch to `Uri::from_shared()` once public.
221            http::Uri::from_maybe_shared(uri_bytes)?
222        };
223        subject = RequestLine(method, uri);
224
225        // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
226        // 1. (irrelevant to Request)
227        // 2. (irrelevant to Request)
228        // 3. Transfer-Encoding: chunked has a chunked body.
229        // 4. If multiple differing Content-Length headers or invalid, close connection.
230        // 5. Content-Length header has a sized body.
231        // 6. Length 0.
232        // 7. (irrelevant to Request)
233
234        let mut decoder = DecodedLength::ZERO;
235        let mut expect_continue = false;
236        let mut con_len = None;
237        let mut is_cl = false;
238        let mut is_te = false;
239        let mut is_te_chunked = false;
240        let mut wants_upgrade = subject.0 == Method::CONNECT;
241
242        let mut header_case_map = if ctx.preserve_header_case {
243            Some(HeaderCaseMap::default())
244        } else {
245            None
246        };
247
248        #[cfg(feature = "ffi")]
249        let mut header_order = if ctx.preserve_header_order {
250            Some(OriginalHeaderOrder::default())
251        } else {
252            None
253        };
254
255        let mut headers = ctx.cached_headers.take().unwrap_or_default();
256
257        headers.reserve(headers_len);
258
259        for header in &headers_indices[..headers_len] {
260            // SAFETY: array is valid up to `headers_len`
261            let header = unsafe { header.assume_init_ref() };
262            let name = header_name!(&slice[header.name.0..header.name.1]);
263            let value = header_value!(slice.slice(header.value.0..header.value.1));
264
265            match name {
266                header::TRANSFER_ENCODING => {
267                    // https://tools.ietf.org/html/rfc7230#section-3.3.3
268                    // If Transfer-Encoding header is present, and 'chunked' is
269                    // not the final encoding, and this is a Request, then it is
270                    // malformed. A server should respond with 400 Bad Request.
271                    if !is_http_11 {
272                        debug!("HTTP/1.0 cannot have Transfer-Encoding header");
273                        return Err(Parse::transfer_encoding_unexpected());
274                    }
275                    is_te = true;
276                    if is_cl && con_len.take().is_some() {
277                        headers.remove(header::CONTENT_LENGTH);
278                    }
279                    if headers::is_chunked_(&value) {
280                        is_te_chunked = true;
281                        decoder = DecodedLength::CHUNKED;
282                    } else {
283                        is_te_chunked = false;
284                    }
285                }
286                header::CONTENT_LENGTH => {
287                    is_cl = true;
288                    if is_te {
289                        continue;
290                    }
291                    let len = headers::content_length_parse(&value)
292                        .ok_or_else(Parse::content_length_invalid)?;
293                    if let Some(prev) = con_len {
294                        if prev != len {
295                            debug!(
296                                "multiple Content-Length headers with different values: [{}, {}]",
297                                prev, len,
298                            );
299                            return Err(Parse::content_length_invalid());
300                        }
301                        // we don't need to append this secondary length
302                        continue;
303                    }
304                    decoder = DecodedLength::checked_new(len)?;
305                    con_len = Some(len);
306                }
307                header::CONNECTION => {
308                    // keep_alive was previously set to default for Version
309                    if keep_alive {
310                        // HTTP/1.1
311                        keep_alive = !headers::connection_close(&value);
312                    } else {
313                        // HTTP/1.0
314                        keep_alive = headers::connection_keep_alive(&value);
315                    }
316                }
317                header::EXPECT => {
318                    // According to https://datatracker.ietf.org/doc/html/rfc2616#section-14.20
319                    // Comparison of expectation values is case-insensitive for unquoted tokens
320                    // (including the 100-continue token)
321                    expect_continue = value.as_bytes().eq_ignore_ascii_case(b"100-continue");
322                }
323                header::UPGRADE => {
324                    // Upgrades are only allowed with HTTP/1.1
325                    wants_upgrade = is_http_11;
326                }
327
328                _ => (),
329            }
330
331            if let Some(ref mut header_case_map) = header_case_map {
332                header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
333            }
334
335            #[cfg(feature = "ffi")]
336            if let Some(ref mut header_order) = header_order {
337                header_order.append(&name);
338            }
339
340            headers.append(name, value);
341        }
342
343        if is_te && !is_te_chunked {
344            debug!("request with transfer-encoding header, but not chunked, bad request");
345            return Err(Parse::transfer_encoding_invalid());
346        }
347
348        if is_te && is_cl {
349            keep_alive = false;
350        }
351
352        let mut extensions = http::Extensions::default();
353
354        if let Some(header_case_map) = header_case_map {
355            extensions.insert(header_case_map);
356        }
357
358        #[cfg(feature = "ffi")]
359        if let Some(header_order) = header_order {
360            extensions.insert(header_order);
361        }
362
363        *ctx.req_method = Some(subject.0.clone());
364
365        Ok(Some(ParsedMessage {
366            head: MessageHead {
367                version,
368                subject,
369                headers,
370                extensions,
371            },
372            decode: decoder,
373            expect_continue,
374            keep_alive,
375            wants_upgrade,
376        }))
377    }
378
379    fn encode(mut msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder> {
380        trace!(
381            "Server::encode status={:?}, body={:?}, req_method={:?}",
382            msg.head.subject,
383            msg.body,
384            msg.req_method
385        );
386
387        let mut wrote_len = false;
388
389        // hyper currently doesn't support returning 1xx status codes as a Response
390        // This is because Service only allows returning a single Response, and
391        // so if you try to reply with a e.g. 100 Continue, you have no way of
392        // replying with the latter status code response.
393        let (ret, is_last) = if msg.head.subject == StatusCode::SWITCHING_PROTOCOLS {
394            (Ok(()), true)
395        } else if msg.req_method == &Some(Method::CONNECT) && msg.head.subject.is_success() {
396            // Sending content-length or transfer-encoding header on 2xx response
397            // to CONNECT is forbidden in RFC 7231.
398            wrote_len = true;
399            (Ok(()), true)
400        } else if msg.head.subject.is_informational() {
401            warn!("response with 1xx status code not supported");
402            *msg.head = MessageHead::default();
403            msg.head.subject = StatusCode::INTERNAL_SERVER_ERROR;
404            msg.body = None;
405            (Err(crate::Error::new_user_unsupported_status_code()), true)
406        } else {
407            (Ok(()), !msg.keep_alive)
408        };
409
410        // In some error cases, we don't know about the invalid message until already
411        // pushing some bytes onto the `dst`. In those cases, we don't want to send
412        // the half-pushed message, so rewind to before.
413        let orig_len = dst.len();
414
415        let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
416        dst.reserve(init_cap);
417
418        let custom_reason_phrase = msg.head.extensions.get::<crate::ext::ReasonPhrase>();
419
420        if msg.head.version == Version::HTTP_11
421            && msg.head.subject == StatusCode::OK
422            && custom_reason_phrase.is_none()
423        {
424            extend(dst, b"HTTP/1.1 200 OK\r\n");
425        } else {
426            match msg.head.version {
427                Version::HTTP_10 => extend(dst, b"HTTP/1.0 "),
428                Version::HTTP_11 => extend(dst, b"HTTP/1.1 "),
429                Version::HTTP_2 => {
430                    debug!("response with HTTP2 version coerced to HTTP/1.1");
431                    extend(dst, b"HTTP/1.1 ");
432                }
433                other => panic!("unexpected response version: {other:?}"),
434            }
435
436            extend(dst, msg.head.subject.as_str().as_bytes());
437            extend(dst, b" ");
438
439            if let Some(reason) = custom_reason_phrase {
440                extend(dst, reason.as_bytes());
441            } else {
442                // a reason MUST be written, as many parsers will expect it.
443                extend(
444                    dst,
445                    msg.head
446                        .subject
447                        .canonical_reason()
448                        .unwrap_or("<none>")
449                        .as_bytes(),
450                );
451            }
452
453            extend(dst, b"\r\n");
454        }
455
456        let orig_headers;
457        let extensions = std::mem::take(&mut msg.head.extensions);
458        let orig_headers = match extensions.get::<HeaderCaseMap>() {
459            None if msg.title_case_headers => {
460                orig_headers = HeaderCaseMap::default();
461                Some(&orig_headers)
462            }
463            orig_headers => orig_headers,
464        };
465        let encoder = if let Some(orig_headers) = orig_headers {
466            Self::encode_headers_with_original_case(
467                msg,
468                dst,
469                is_last,
470                orig_len,
471                wrote_len,
472                orig_headers,
473            )?
474        } else {
475            Self::encode_headers_with_lower_case(msg, dst, is_last, orig_len, wrote_len)?
476        };
477
478        ret.map(|()| encoder)
479    }
480
481    fn on_error(err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
482        use crate::error::Kind;
483        let status = match *err.kind() {
484            Kind::Parse(Parse::Method)
485            | Kind::Parse(Parse::Header(_))
486            | Kind::Parse(Parse::Uri)
487            | Kind::Parse(Parse::Version) => StatusCode::BAD_REQUEST,
488            Kind::Parse(Parse::TooLarge) => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE,
489            Kind::Parse(Parse::UriTooLong) => StatusCode::URI_TOO_LONG,
490            _ => return None,
491        };
492
493        debug!("sending automatic response ({}) for parse error", status);
494        let msg = MessageHead {
495            subject: status,
496            ..Default::default()
497        };
498        Some(msg)
499    }
500
501    fn is_server() -> bool {
502        true
503    }
504
505    fn update_date() {
506        date::update();
507    }
508}
509
510#[cfg(feature = "server")]
511impl Server {
512    fn can_have_body(method: Option<&Method>, status: StatusCode) -> bool {
513        Server::can_chunked(method, status)
514    }
515
516    fn can_chunked(method: Option<&Method>, status: StatusCode) -> bool {
517        if method == Some(&Method::HEAD)
518            || method == Some(&Method::CONNECT) && status.is_success()
519            || status.is_informational()
520        {
521            false
522        } else {
523            !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED)
524        }
525    }
526
527    fn can_have_content_length(method: Option<&Method>, status: StatusCode) -> bool {
528        if status.is_informational() || method == Some(&Method::CONNECT) && status.is_success() {
529            false
530        } else {
531            !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED)
532        }
533    }
534
535    fn can_have_implicit_zero_content_length(method: Option<&Method>, status: StatusCode) -> bool {
536        Server::can_have_content_length(method, status) && method != Some(&Method::HEAD)
537    }
538
539    fn encode_headers_with_lower_case(
540        msg: Encode<'_, StatusCode>,
541        dst: &mut Vec<u8>,
542        is_last: bool,
543        orig_len: usize,
544        wrote_len: bool,
545    ) -> crate::Result<Encoder> {
546        struct LowercaseWriter;
547
548        impl HeaderNameWriter for LowercaseWriter {
549            #[inline]
550            fn write_full_header_line(
551                &mut self,
552                dst: &mut Vec<u8>,
553                line: &str,
554                _: (HeaderName, &str),
555            ) {
556                extend(dst, line.as_bytes());
557            }
558
559            #[inline]
560            fn write_header_name_with_colon(
561                &mut self,
562                dst: &mut Vec<u8>,
563                name_with_colon: &str,
564                _: HeaderName,
565            ) {
566                extend(dst, name_with_colon.as_bytes());
567            }
568
569            #[inline]
570            fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName) {
571                extend(dst, name.as_str().as_bytes());
572            }
573        }
574
575        Self::encode_headers(msg, dst, is_last, orig_len, wrote_len, LowercaseWriter)
576    }
577
578    #[cold]
579    #[inline(never)]
580    fn encode_headers_with_original_case(
581        msg: Encode<'_, StatusCode>,
582        dst: &mut Vec<u8>,
583        is_last: bool,
584        orig_len: usize,
585        wrote_len: bool,
586        orig_headers: &HeaderCaseMap,
587    ) -> crate::Result<Encoder> {
588        struct OrigCaseWriter<'map> {
589            map: &'map HeaderCaseMap,
590            current: Option<(HeaderName, ValueIter<'map, Bytes>)>,
591            title_case_headers: bool,
592        }
593
594        impl HeaderNameWriter for OrigCaseWriter<'_> {
595            #[inline]
596            fn write_full_header_line(
597                &mut self,
598                dst: &mut Vec<u8>,
599                _: &str,
600                (name, rest): (HeaderName, &str),
601            ) {
602                self.write_header_name(dst, &name);
603                extend(dst, rest.as_bytes());
604            }
605
606            #[inline]
607            fn write_header_name_with_colon(
608                &mut self,
609                dst: &mut Vec<u8>,
610                _: &str,
611                name: HeaderName,
612            ) {
613                self.write_header_name(dst, &name);
614                extend(dst, b": ");
615            }
616
617            #[inline]
618            fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName) {
619                let Self {
620                    map,
621                    ref mut current,
622                    title_case_headers,
623                } = *self;
624                if current.as_ref().map_or(true, |(last, _)| last != name) {
625                    *current = None;
626                }
627                let (_, values) =
628                    current.get_or_insert_with(|| (name.clone(), map.get_all_internal(name)));
629
630                if let Some(orig_name) = values.next() {
631                    extend(dst, orig_name);
632                } else if title_case_headers {
633                    title_case(dst, name.as_str().as_bytes());
634                } else {
635                    extend(dst, name.as_str().as_bytes());
636                }
637            }
638        }
639
640        let header_name_writer = OrigCaseWriter {
641            map: orig_headers,
642            current: None,
643            title_case_headers: msg.title_case_headers,
644        };
645
646        Self::encode_headers(msg, dst, is_last, orig_len, wrote_len, header_name_writer)
647    }
648
649    #[inline]
650    fn encode_headers<W>(
651        msg: Encode<'_, StatusCode>,
652        dst: &mut Vec<u8>,
653        mut is_last: bool,
654        orig_len: usize,
655        mut wrote_len: bool,
656        mut header_name_writer: W,
657    ) -> crate::Result<Encoder>
658    where
659        W: HeaderNameWriter,
660    {
661        // In some error cases, we don't know about the invalid message until already
662        // pushing some bytes onto the `dst`. In those cases, we don't want to send
663        // the half-pushed message, so rewind to before.
664        let rewind = |dst: &mut Vec<u8>| {
665            dst.truncate(orig_len);
666        };
667
668        let mut encoder = Encoder::length(0);
669        let mut allowed_trailer_fields: Option<Vec<HeaderName>> = None;
670        let mut wrote_date = false;
671        let mut cur_name = None;
672        let mut is_name_written = false;
673        let mut must_write_chunked = false;
674        let mut prev_con_len = None;
675
676        macro_rules! handle_is_name_written {
677            () => {{
678                if is_name_written {
679                    // we need to clean up and write the newline
680                    debug_assert_ne!(
681                        &dst[dst.len() - 2..],
682                        b"\r\n",
683                        "previous header wrote newline but set is_name_written"
684                    );
685
686                    if must_write_chunked {
687                        extend(dst, b", chunked\r\n");
688                    } else {
689                        extend(dst, b"\r\n");
690                    }
691                }
692            }};
693        }
694
695        'headers: for (opt_name, value) in msg.head.headers.drain() {
696            if let Some(n) = opt_name {
697                cur_name = Some(n);
698                handle_is_name_written!();
699                is_name_written = false;
700            }
701            let name = cur_name.as_ref().expect("current header name");
702            match *name {
703                header::CONTENT_LENGTH => {
704                    if wrote_len && !is_name_written {
705                        warn!("unexpected content-length found, canceling");
706                        rewind(dst);
707                        return Err(crate::Error::new_user_header());
708                    }
709                    match msg.body {
710                        Some(BodyLength::Known(known_len)) => {
711                            // The Body claims to know a length, and
712                            // the headers are already set. For performance
713                            // reasons, we are just going to trust that
714                            // the values match.
715                            //
716                            // In debug builds, we'll assert they are the
717                            // same to help developers find bugs.
718                            #[cfg(debug_assertions)]
719                            {
720                                if let Some(len) = headers::content_length_parse(&value) {
721                                    if msg.req_method != &Some(Method::HEAD) || known_len != 0 {
722                                        assert!(
723                                        len == known_len,
724                                        "payload claims content-length of {known_len}, custom content-length header claims {len}",
725                                    );
726                                    }
727                                }
728                            }
729
730                            if !is_name_written {
731                                encoder = Encoder::length(known_len);
732                                header_name_writer.write_header_name_with_colon(
733                                    dst,
734                                    "content-length: ",
735                                    header::CONTENT_LENGTH,
736                                );
737                                extend(dst, value.as_bytes());
738                                wrote_len = true;
739                                is_name_written = true;
740                            }
741                            continue 'headers;
742                        }
743                        Some(BodyLength::Unknown) => {
744                            // The Body impl didn't know how long the
745                            // body is, but a length header was included.
746                            // We have to parse the value to return our
747                            // Encoder...
748
749                            if let Some(len) = headers::content_length_parse(&value) {
750                                if let Some(prev) = prev_con_len {
751                                    if prev != len {
752                                        warn!(
753                                            "multiple Content-Length values found: [{}, {}]",
754                                            prev, len
755                                        );
756                                        rewind(dst);
757                                        return Err(crate::Error::new_user_header());
758                                    }
759                                    debug_assert!(is_name_written);
760                                    continue 'headers;
761                                } else {
762                                    // we haven't written content-length yet!
763                                    encoder = Encoder::length(len);
764                                    header_name_writer.write_header_name_with_colon(
765                                        dst,
766                                        "content-length: ",
767                                        header::CONTENT_LENGTH,
768                                    );
769                                    extend(dst, value.as_bytes());
770                                    wrote_len = true;
771                                    is_name_written = true;
772                                    prev_con_len = Some(len);
773                                    continue 'headers;
774                                }
775                            } else {
776                                warn!("illegal Content-Length value: {:?}", value);
777                                rewind(dst);
778                                return Err(crate::Error::new_user_header());
779                            }
780                        }
781                        None => {
782                            // We have no body to actually send,
783                            // but the headers claim a content-length.
784                            // There's only 2 ways this makes sense:
785                            //
786                            // - The header says the length is `0`.
787                            // - This is a response to a `HEAD` request.
788                            if msg.req_method == &Some(Method::HEAD) {
789                                debug_assert_eq!(encoder, Encoder::length(0));
790                            } else {
791                                if value.as_bytes() != b"0" {
792                                    warn!(
793                                        "content-length value found, but empty body provided: {:?}",
794                                        value
795                                    );
796                                }
797                                continue 'headers;
798                            }
799                        }
800                    }
801                    wrote_len = true;
802                }
803                header::TRANSFER_ENCODING => {
804                    if wrote_len && !is_name_written {
805                        warn!("unexpected transfer-encoding found, canceling");
806                        rewind(dst);
807                        return Err(crate::Error::new_user_header());
808                    }
809                    // check that we actually can send a chunked body...
810                    if msg.head.version == Version::HTTP_10
811                        || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
812                    {
813                        continue;
814                    }
815                    wrote_len = true;
816                    // Must check each value, because `chunked` needs to be the
817                    // last encoding, or else we add it.
818                    must_write_chunked = !headers::is_chunked_(&value);
819
820                    if !is_name_written {
821                        encoder = Encoder::chunked();
822                        is_name_written = true;
823                        header_name_writer.write_header_name_with_colon(
824                            dst,
825                            "transfer-encoding: ",
826                            header::TRANSFER_ENCODING,
827                        );
828                        extend(dst, value.as_bytes());
829                    } else {
830                        extend(dst, b", ");
831                        extend(dst, value.as_bytes());
832                    }
833                    continue 'headers;
834                }
835                header::CONNECTION => {
836                    if !is_last && headers::connection_close(&value) {
837                        is_last = true;
838                    }
839                    if !is_name_written {
840                        is_name_written = true;
841                        header_name_writer.write_header_name_with_colon(
842                            dst,
843                            "connection: ",
844                            header::CONNECTION,
845                        );
846                        extend(dst, value.as_bytes());
847                    } else {
848                        extend(dst, b", ");
849                        extend(dst, value.as_bytes());
850                    }
851                    continue 'headers;
852                }
853                header::DATE => {
854                    wrote_date = true;
855                }
856                header::TRAILER => {
857                    // check that we actually can send a chunked body...
858                    if msg.head.version == Version::HTTP_10
859                        || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
860                    {
861                        continue;
862                    }
863
864                    if !is_name_written {
865                        is_name_written = true;
866                        header_name_writer.write_header_name_with_colon(
867                            dst,
868                            "trailer: ",
869                            header::TRAILER,
870                        );
871                        extend(dst, value.as_bytes());
872                    } else {
873                        extend(dst, b", ");
874                        extend(dst, value.as_bytes());
875                    }
876
877                    // Parse the Trailer header value into HeaderNames.
878                    // The value may contain comma-separated names.
879                    // HeaderName normalizes to lowercase for case-insensitive matching.
880                    if let Ok(value_str) = value.to_str() {
881                        let names: Vec<HeaderName> = value_str
882                            .split(',')
883                            .filter_map(|s| HeaderName::from_bytes(s.trim().as_bytes()).ok())
884                            .collect();
885
886                        match allowed_trailer_fields {
887                            Some(ref mut fields) => {
888                                fields.extend(names);
889                            }
890                            None => {
891                                allowed_trailer_fields = Some(names);
892                            }
893                        }
894                    }
895
896                    continue 'headers;
897                }
898                _ => (),
899            }
900            //TODO: this should perhaps instead combine them into
901            //single lines, as RFC7230 suggests is preferable.
902
903            // non-special write Name and Value
904            debug_assert!(
905                !is_name_written,
906                "{name:?} set is_name_written and didn't continue loop",
907            );
908            header_name_writer.write_header_name(dst, name);
909            extend(dst, b": ");
910            extend(dst, value.as_bytes());
911            extend(dst, b"\r\n");
912        }
913
914        handle_is_name_written!();
915
916        if !wrote_len {
917            encoder = match msg.body {
918                Some(BodyLength::Unknown) => {
919                    if msg.head.version == Version::HTTP_10
920                        || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
921                    {
922                        Encoder::close_delimited()
923                    } else {
924                        header_name_writer.write_full_header_line(
925                            dst,
926                            "transfer-encoding: chunked\r\n",
927                            (header::TRANSFER_ENCODING, ": chunked\r\n"),
928                        );
929                        Encoder::chunked()
930                    }
931                }
932                None | Some(BodyLength::Known(0)) => {
933                    if Server::can_have_implicit_zero_content_length(
934                        msg.req_method.as_ref(),
935                        msg.head.subject,
936                    ) {
937                        header_name_writer.write_full_header_line(
938                            dst,
939                            "content-length: 0\r\n",
940                            (header::CONTENT_LENGTH, ": 0\r\n"),
941                        );
942                    }
943                    Encoder::length(0)
944                }
945                Some(BodyLength::Known(len)) => {
946                    if !Server::can_have_content_length(msg.req_method.as_ref(), msg.head.subject) {
947                        Encoder::length(0)
948                    } else {
949                        header_name_writer.write_header_name_with_colon(
950                            dst,
951                            "content-length: ",
952                            header::CONTENT_LENGTH,
953                        );
954                        extend(dst, ::itoa::Buffer::new().format(len).as_bytes());
955                        extend(dst, b"\r\n");
956                        Encoder::length(len)
957                    }
958                }
959            };
960        }
961
962        if !Server::can_have_body(msg.req_method.as_ref(), msg.head.subject) {
963            trace!(
964                "server body forced to 0; method={:?}, status={:?}",
965                msg.req_method,
966                msg.head.subject
967            );
968            encoder = Encoder::length(0);
969        }
970
971        // cached date is much faster than formatting every request
972        // don't force the write if disabled
973        if !wrote_date && msg.date_header {
974            dst.reserve(date::DATE_VALUE_LENGTH + 8);
975            header_name_writer.write_header_name_with_colon(dst, "date: ", header::DATE);
976            date::extend(dst);
977            extend(dst, b"\r\n\r\n");
978        } else {
979            extend(dst, b"\r\n");
980        }
981
982        if encoder.is_chunked() {
983            if let Some(allowed_trailer_fields) = allowed_trailer_fields {
984                encoder = encoder.into_chunked_with_trailing_fields(allowed_trailer_fields);
985            }
986        }
987
988        Ok(encoder.set_last(is_last))
989    }
990
991    /// Helper for zero-copy parsing of request path URI.
992    #[inline]
993    fn record_path_range(bytes: &[u8], req_path: &str) -> std::ops::Range<usize> {
994        let bytes_ptr = bytes.as_ptr() as usize;
995        let start = req_path.as_ptr() as usize - bytes_ptr;
996        let end = start + req_path.len();
997        std::ops::Range { start, end }
998    }
999}
1000
1001#[cfg(feature = "server")]
1002trait HeaderNameWriter {
1003    fn write_full_header_line(
1004        &mut self,
1005        dst: &mut Vec<u8>,
1006        line: &str,
1007        name_value_pair: (HeaderName, &str),
1008    );
1009    fn write_header_name_with_colon(
1010        &mut self,
1011        dst: &mut Vec<u8>,
1012        name_with_colon: &str,
1013        name: HeaderName,
1014    );
1015    fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName);
1016}
1017
1018#[cfg(feature = "client")]
1019impl Http1Transaction for Client {
1020    type Incoming = StatusCode;
1021    type Outgoing = RequestLine;
1022    #[cfg(feature = "tracing")]
1023    const LOG: &'static str = "{role=client}";
1024
1025    fn parse(buf: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<StatusCode> {
1026        debug_assert!(!buf.is_empty(), "parse called with empty buf");
1027
1028        // Loop to skip information status code headers (100 Continue, etc).
1029        loop {
1030            let mut headers_indices: SmallVec<[MaybeUninit<HeaderIndices>; DEFAULT_MAX_HEADERS]> =
1031                match ctx.h1_max_headers {
1032                    Some(cap) => smallvec![MaybeUninit::uninit(); cap],
1033                    None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
1034                };
1035            let (len, status, reason, version, headers_len) = {
1036                let mut headers: SmallVec<
1037                    [MaybeUninit<httparse::Header<'_>>; DEFAULT_MAX_HEADERS],
1038                > = match ctx.h1_max_headers {
1039                    Some(cap) => smallvec![MaybeUninit::uninit(); cap],
1040                    None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
1041                };
1042                trace!(bytes = buf.len(), "Response.parse");
1043                let mut res = httparse::Response::new(&mut []);
1044                let bytes = buf.as_ref();
1045                match ctx.h1_parser_config.parse_response_with_uninit_headers(
1046                    &mut res,
1047                    bytes,
1048                    &mut headers,
1049                ) {
1050                    Ok(httparse::Status::Complete(len)) => {
1051                        trace!("Response.parse Complete({})", len);
1052                        let status = StatusCode::from_u16(res.code.expect("httparse completed"))?;
1053
1054                        let reason = {
1055                            let reason = res.reason.expect("httparse completed");
1056                            // Only save the reason phrase if it isn't the canonical reason
1057                            if Some(reason) != status.canonical_reason() {
1058                                Some(Bytes::copy_from_slice(reason.as_bytes()))
1059                            } else {
1060                                None
1061                            }
1062                        };
1063
1064                        let version = if res.version.expect("httparse completed") == 1 {
1065                            Version::HTTP_11
1066                        } else {
1067                            Version::HTTP_10
1068                        };
1069                        record_header_indices(bytes, res.headers, &mut headers_indices)?;
1070                        let headers_len = res.headers.len();
1071                        (len, status, reason, version, headers_len)
1072                    }
1073                    Ok(httparse::Status::Partial) => return Ok(None),
1074                    Err(httparse::Error::Version) if ctx.h09_responses => {
1075                        trace!("Response.parse accepted HTTP/0.9 response");
1076
1077                        (0, StatusCode::OK, None, Version::HTTP_09, 0)
1078                    }
1079                    Err(e) => return Err(e.into()),
1080                }
1081            };
1082
1083            let mut slice = buf.split_to(len);
1084
1085            if ctx
1086                .h1_parser_config
1087                .obsolete_multiline_headers_in_responses_are_allowed()
1088            {
1089                for header in &mut headers_indices[..headers_len] {
1090                    // SAFETY: array is valid up to `headers_len`
1091                    let header = unsafe { header.assume_init_mut() };
1092                    Client::obs_fold_line(&mut slice, header);
1093                }
1094            }
1095
1096            let slice = slice.freeze();
1097
1098            let mut headers = ctx.cached_headers.take().unwrap_or_default();
1099
1100            let mut keep_alive = version == Version::HTTP_11;
1101
1102            let mut header_case_map = if ctx.preserve_header_case {
1103                Some(HeaderCaseMap::default())
1104            } else {
1105                None
1106            };
1107
1108            #[cfg(feature = "ffi")]
1109            let mut header_order = if ctx.preserve_header_order {
1110                Some(OriginalHeaderOrder::default())
1111            } else {
1112                None
1113            };
1114
1115            headers.reserve(headers_len);
1116            for header in &headers_indices[..headers_len] {
1117                // SAFETY: array is valid up to `headers_len`
1118                let header = unsafe { header.assume_init_ref() };
1119                let name = header_name!(&slice[header.name.0..header.name.1]);
1120                let value = header_value!(slice.slice(header.value.0..header.value.1));
1121
1122                if let header::CONNECTION = name {
1123                    // keep_alive was previously set to default for Version
1124                    if keep_alive {
1125                        // HTTP/1.1
1126                        keep_alive = !headers::connection_close(&value);
1127                    } else {
1128                        // HTTP/1.0
1129                        keep_alive = headers::connection_keep_alive(&value);
1130                    }
1131                }
1132
1133                if let Some(ref mut header_case_map) = header_case_map {
1134                    header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
1135                }
1136
1137                #[cfg(feature = "ffi")]
1138                if let Some(ref mut header_order) = header_order {
1139                    header_order.append(&name);
1140                }
1141
1142                headers.append(name, value);
1143            }
1144
1145            let mut extensions = http::Extensions::default();
1146
1147            if let Some(header_case_map) = header_case_map {
1148                extensions.insert(header_case_map);
1149            }
1150
1151            #[cfg(feature = "ffi")]
1152            if let Some(header_order) = header_order {
1153                extensions.insert(header_order);
1154            }
1155
1156            if let Some(reason) = reason {
1157                // Safety: httparse ensures that only valid reason phrase bytes are present in this
1158                // field.
1159                let reason = crate::ext::ReasonPhrase::from_bytes_unchecked(reason);
1160                extensions.insert(reason);
1161            }
1162
1163            let head = MessageHead {
1164                version,
1165                subject: status,
1166                headers,
1167                extensions,
1168            };
1169            if let Some((decode, is_upgrade)) = Client::decoder(&head, ctx.req_method)? {
1170                return Ok(Some(ParsedMessage {
1171                    head,
1172                    decode,
1173                    expect_continue: false,
1174                    // a client upgrade means the connection can't be used
1175                    // again, as it is definitely upgrading.
1176                    keep_alive: keep_alive && !is_upgrade,
1177                    wants_upgrade: is_upgrade,
1178                }));
1179            }
1180
1181            if head.subject.is_informational() {
1182                if let Some(callback) = ctx.on_informational {
1183                    callback.call(head.into_response(()));
1184                }
1185            }
1186
1187            // Parsing a 1xx response could have consumed the buffer, check if
1188            // it is empty now...
1189            if buf.is_empty() {
1190                return Ok(None);
1191            }
1192        }
1193    }
1194
1195    fn encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder> {
1196        trace!(
1197            "Client::encode method={:?}, body={:?}",
1198            msg.head.subject.0,
1199            msg.body
1200        );
1201
1202        *msg.req_method = Some(msg.head.subject.0.clone());
1203
1204        let body = Client::set_length(msg.head, msg.body);
1205
1206        let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
1207        dst.reserve(init_cap);
1208
1209        extend(dst, msg.head.subject.0.as_str().as_bytes());
1210        extend(dst, b" ");
1211        //TODO: add API to http::Uri to encode without std::fmt
1212        let _ = write!(FastWrite(dst), "{} ", msg.head.subject.1);
1213
1214        match msg.head.version {
1215            Version::HTTP_10 => extend(dst, b"HTTP/1.0"),
1216            Version::HTTP_11 => extend(dst, b"HTTP/1.1"),
1217            Version::HTTP_2 => {
1218                debug!("request with HTTP2 version coerced to HTTP/1.1");
1219                extend(dst, b"HTTP/1.1");
1220            }
1221            other => panic!("unexpected request version: {other:?}"),
1222        }
1223        extend(dst, b"\r\n");
1224
1225        if let Some(orig_headers) = msg.head.extensions.get::<HeaderCaseMap>() {
1226            write_headers_original_case(
1227                &msg.head.headers,
1228                orig_headers,
1229                dst,
1230                msg.title_case_headers,
1231            );
1232        } else if msg.title_case_headers {
1233            write_headers_title_case(&msg.head.headers, dst);
1234        } else {
1235            write_headers(&msg.head.headers, dst);
1236        }
1237
1238        extend(dst, b"\r\n");
1239        msg.head.headers.clear(); //TODO: remove when switching to drain()
1240
1241        Ok(body)
1242    }
1243
1244    fn on_error(_err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
1245        // we can't tell the server about any errors it creates
1246        None
1247    }
1248
1249    fn is_client() -> bool {
1250        true
1251    }
1252}
1253
1254#[cfg(feature = "client")]
1255impl Client {
1256    /// Returns `Some(length, wants_upgrade)` if successful.
1257    ///
1258    /// Returns `None` if this message head should be skipped (like a 100 status).
1259    fn decoder(
1260        inc: &MessageHead<StatusCode>,
1261        method: &mut Option<Method>,
1262    ) -> Result<Option<(DecodedLength, bool)>, Parse> {
1263        // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
1264        // 1. HEAD responses, and Status 1xx, 204, and 304 cannot have a body.
1265        // 2. Status 2xx to a CONNECT cannot have a body.
1266        // 3. Transfer-Encoding: chunked has a chunked body.
1267        // 4. If multiple differing Content-Length headers or invalid, close connection.
1268        // 5. Content-Length header has a sized body.
1269        // 6. (irrelevant to Response)
1270        // 7. Read till EOF.
1271
1272        match inc.subject.as_u16() {
1273            101 => {
1274                return Ok(Some((DecodedLength::ZERO, true)));
1275            }
1276            100 | 102..=199 => {
1277                trace!("ignoring informational response: {}", inc.subject.as_u16());
1278                return Ok(None);
1279            }
1280            204 | 304 => return Ok(Some((DecodedLength::ZERO, false))),
1281            _ => (),
1282        }
1283        match *method {
1284            Some(Method::HEAD) => {
1285                return Ok(Some((DecodedLength::ZERO, false)));
1286            }
1287            Some(Method::CONNECT) => {
1288                if let 200..=299 = inc.subject.as_u16() {
1289                    return Ok(Some((DecodedLength::ZERO, true)));
1290                }
1291            }
1292            Some(_) => {}
1293            None => {
1294                trace!("Client::decoder is missing the Method");
1295            }
1296        }
1297
1298        if inc.headers.contains_key(header::TRANSFER_ENCODING) {
1299            // https://tools.ietf.org/html/rfc7230#section-3.3.3
1300            // If Transfer-Encoding header is present, and 'chunked' is
1301            // not the final encoding, and this is a Request, then it is
1302            // malformed. A server should respond with 400 Bad Request.
1303            if inc.version == Version::HTTP_10 {
1304                debug!("HTTP/1.0 cannot have Transfer-Encoding header");
1305                Err(Parse::transfer_encoding_unexpected())
1306            } else if headers::transfer_encoding_is_chunked(&inc.headers) {
1307                Ok(Some((DecodedLength::CHUNKED, false)))
1308            } else {
1309                trace!("not chunked, read till eof");
1310                Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1311            }
1312        } else if let Some(len) = headers::content_length_parse_all(&inc.headers) {
1313            Ok(Some((DecodedLength::checked_new(len)?, false)))
1314        } else if inc.headers.contains_key(header::CONTENT_LENGTH) {
1315            debug!("illegal Content-Length header");
1316            Err(Parse::content_length_invalid())
1317        } else {
1318            trace!("neither Transfer-Encoding nor Content-Length");
1319            Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1320        }
1321    }
1322    fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
1323        let body = if let Some(body) = body {
1324            body
1325        } else {
1326            head.headers.remove(header::TRANSFER_ENCODING);
1327            return Encoder::length(0);
1328        };
1329
1330        // HTTP/1.0 doesn't know about chunked
1331        let can_chunked = head.version == Version::HTTP_11;
1332        let headers = &mut head.headers;
1333
1334        // If the user already set specific headers, we should respect them, regardless
1335        // of what the Body knows about itself. They set them for a reason.
1336
1337        // Because of the borrow checker, we can't check the for an existing
1338        // Content-Length header while holding an `Entry` for the Transfer-Encoding
1339        // header, so unfortunately, we must do the check here, first.
1340
1341        let existing_con_len = headers::content_length_parse_all(headers);
1342        let mut should_remove_con_len = false;
1343
1344        if !can_chunked {
1345            // Chunked isn't legal, so if it is set, we need to remove it.
1346            if headers.remove(header::TRANSFER_ENCODING).is_some() {
1347                trace!("removing illegal transfer-encoding header");
1348            }
1349
1350            return if let Some(len) = existing_con_len {
1351                Encoder::length(len)
1352            } else if let BodyLength::Known(len) = body {
1353                set_content_length(headers, len)
1354            } else {
1355                // HTTP/1.0 client requests without a content-length
1356                // cannot have any body at all.
1357                Encoder::length(0)
1358            };
1359        }
1360
1361        // If the user set a transfer-encoding, respect that. Let's just
1362        // make sure `chunked` is the final encoding.
1363        let encoder = match headers.entry(header::TRANSFER_ENCODING) {
1364            Entry::Occupied(te) => {
1365                should_remove_con_len = true;
1366                if headers::is_chunked(te.iter()) {
1367                    Some(Encoder::chunked())
1368                } else {
1369                    warn!("user provided transfer-encoding does not end in 'chunked'");
1370
1371                    // There's a Transfer-Encoding, but it doesn't end in 'chunked'!
1372                    // An example that could trigger this:
1373                    //
1374                    //     Transfer-Encoding: gzip
1375                    //
1376                    // This can be bad, depending on if this is a request or a
1377                    // response.
1378                    //
1379                    // - A request is illegal if there is a `Transfer-Encoding`
1380                    //   but it doesn't end in `chunked`.
1381                    // - A response that has `Transfer-Encoding` but doesn't
1382                    //   end in `chunked` isn't illegal, it just forces this
1383                    //   to be close-delimited.
1384                    //
1385                    // We can try to repair this, by adding `chunked` ourselves.
1386
1387                    headers::add_chunked(te);
1388                    Some(Encoder::chunked())
1389                }
1390            }
1391            Entry::Vacant(te) => {
1392                if let Some(len) = existing_con_len {
1393                    Some(Encoder::length(len))
1394                } else if let BodyLength::Unknown = body {
1395                    // GET, HEAD, and CONNECT almost never have bodies.
1396                    //
1397                    // So instead of sending a "chunked" body with a 0-chunk,
1398                    // assume no body here. If you *must* send a body,
1399                    // set the headers explicitly.
1400                    match head.subject.0 {
1401                        Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)),
1402                        _ => {
1403                            te.insert(HeaderValue::from_static("chunked"));
1404                            Some(Encoder::chunked())
1405                        }
1406                    }
1407                } else {
1408                    None
1409                }
1410            }
1411        };
1412
1413        let encoder = encoder.map(|enc| {
1414            if enc.is_chunked() {
1415                // Parse Trailer header values into HeaderNames.
1416                // Each Trailer header value may contain comma-separated names.
1417                // HeaderName normalizes to lowercase, enabling case-insensitive matching.
1418                let allowed_trailer_fields: Vec<HeaderName> = headers
1419                    .get_all(header::TRAILER)
1420                    .iter()
1421                    .filter_map(|hv| hv.to_str().ok())
1422                    .flat_map(|s| s.split(','))
1423                    .filter_map(|s| HeaderName::from_bytes(s.trim().as_bytes()).ok())
1424                    .collect();
1425
1426                if !allowed_trailer_fields.is_empty() {
1427                    return enc.into_chunked_with_trailing_fields(allowed_trailer_fields);
1428                }
1429            }
1430
1431            enc
1432        });
1433
1434        // This is because we need a second mutable borrow to remove
1435        // content-length header.
1436        if let Some(encoder) = encoder {
1437            if should_remove_con_len && existing_con_len.is_some() {
1438                headers.remove(header::CONTENT_LENGTH);
1439            }
1440            return encoder;
1441        }
1442
1443        // User didn't set transfer-encoding, AND we know body length,
1444        // so we can just set the Content-Length automatically.
1445
1446        let len = if let BodyLength::Known(len) = body {
1447            len
1448        } else {
1449            unreachable!("BodyLength::Unknown would set chunked");
1450        };
1451
1452        set_content_length(headers, len)
1453    }
1454
1455    fn obs_fold_line(all: &mut [u8], idx: &mut HeaderIndices) {
1456        // If the value has obs-folded text, then in-place shift the bytes out
1457        // of here.
1458        //
1459        // https://httpwg.org/specs/rfc9112.html#line.folding
1460        //
1461        // > A user agent that receives an obs-fold MUST replace each received
1462        // > obs-fold with one or more SP octets prior to interpreting the
1463        // > field value.
1464        //
1465        // This means strings like "\r\n\t foo" must replace the "\r\n\t " with
1466        // a single space.
1467
1468        let buf = &mut all[idx.value.0..idx.value.1];
1469
1470        // look for a newline, otherwise bail out
1471        let first_nl = match buf.iter().position(|b| *b == b'\n') {
1472            Some(i) => i,
1473            None => return,
1474        };
1475
1476        // not on standard slices because whatever, sigh
1477        fn trim_start(mut s: &[u8]) -> &[u8] {
1478            while let [first, rest @ ..] = s {
1479                if first.is_ascii_whitespace() {
1480                    s = rest;
1481                } else {
1482                    break;
1483                }
1484            }
1485            s
1486        }
1487
1488        fn trim_end(mut s: &[u8]) -> &[u8] {
1489            while let [rest @ .., last] = s {
1490                if last.is_ascii_whitespace() {
1491                    s = rest;
1492                } else {
1493                    break;
1494                }
1495            }
1496            s
1497        }
1498
1499        fn trim(s: &[u8]) -> &[u8] {
1500            trim_start(trim_end(s))
1501        }
1502
1503        // TODO(perf): we could do the moves in-place, but this is so uncommon
1504        // that it shouldn't matter.
1505        let mut unfolded = trim_end(&buf[..first_nl]).to_vec();
1506        for line in buf[first_nl + 1..].split(|b| *b == b'\n') {
1507            unfolded.push(b' ');
1508            unfolded.extend_from_slice(trim(line));
1509        }
1510        buf[..unfolded.len()].copy_from_slice(&unfolded);
1511        idx.value.1 = idx.value.0 + unfolded.len();
1512    }
1513}
1514
1515#[cfg(feature = "client")]
1516fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
1517    // At this point, there should not be a valid Content-Length
1518    // header. However, since we'll be indexing in anyways, we can
1519    // warn the user if there was an existing illegal header.
1520    //
1521    // Or at least, we can in theory. It's actually a little bit slower,
1522    // so perhaps only do that while the user is developing/testing.
1523
1524    if cfg!(debug_assertions) {
1525        match headers.entry(header::CONTENT_LENGTH) {
1526            Entry::Occupied(mut cl) => {
1527                // Internal sanity check, we should have already determined
1528                // that the header was illegal before calling this function.
1529                debug_assert!(headers::content_length_parse_all_values(cl.iter()).is_none());
1530                // Uh oh, the user set `Content-Length` headers, but set bad ones.
1531                // This would be an illegal message anyways, so let's try to repair
1532                // with our known good length.
1533                error!("user provided content-length header was invalid");
1534
1535                cl.insert(HeaderValue::from(len));
1536                Encoder::length(len)
1537            }
1538            Entry::Vacant(cl) => {
1539                cl.insert(HeaderValue::from(len));
1540                Encoder::length(len)
1541            }
1542        }
1543    } else {
1544        headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
1545        Encoder::length(len)
1546    }
1547}
1548
1549#[derive(Clone, Copy)]
1550struct HeaderIndices {
1551    name: (usize, usize),
1552    value: (usize, usize),
1553}
1554
1555fn record_header_indices(
1556    bytes: &[u8],
1557    headers: &[httparse::Header<'_>],
1558    indices: &mut [MaybeUninit<HeaderIndices>],
1559) -> Result<(), crate::error::Parse> {
1560    let bytes_ptr = bytes.as_ptr() as usize;
1561
1562    for (header, indices) in headers.iter().zip(indices.iter_mut()) {
1563        if header.name.len() >= (1 << 16) {
1564            debug!("header name larger than 64kb: {:?}", header.name);
1565            return Err(crate::error::Parse::TooLarge);
1566        }
1567        let name_start = header.name.as_ptr() as usize - bytes_ptr;
1568        let name_end = name_start + header.name.len();
1569        let value_start = header.value.as_ptr() as usize - bytes_ptr;
1570        let value_end = value_start + header.value.len();
1571
1572        indices.write(HeaderIndices {
1573            name: (name_start, name_end),
1574            value: (value_start, value_end),
1575        });
1576    }
1577
1578    Ok(())
1579}
1580
1581// Write header names as title case. The header name is assumed to be ASCII.
1582fn title_case(dst: &mut Vec<u8>, name: &[u8]) {
1583    dst.reserve(name.len());
1584
1585    // Ensure first character is uppercased
1586    let mut prev = b'-';
1587    for &(mut c) in name {
1588        if prev == b'-' {
1589            c.make_ascii_uppercase();
1590        }
1591        dst.push(c);
1592        prev = c;
1593    }
1594}
1595
1596pub(crate) fn write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>) {
1597    for (name, value) in headers {
1598        title_case(dst, name.as_str().as_bytes());
1599        extend(dst, b": ");
1600        extend(dst, value.as_bytes());
1601        extend(dst, b"\r\n");
1602    }
1603}
1604
1605pub(crate) fn write_headers(headers: &HeaderMap, dst: &mut Vec<u8>) {
1606    for (name, value) in headers {
1607        extend(dst, name.as_str().as_bytes());
1608        extend(dst, b": ");
1609        extend(dst, value.as_bytes());
1610        extend(dst, b"\r\n");
1611    }
1612}
1613
1614#[cold]
1615#[cfg(feature = "client")]
1616fn write_headers_original_case(
1617    headers: &HeaderMap,
1618    orig_case: &HeaderCaseMap,
1619    dst: &mut Vec<u8>,
1620    title_case_headers: bool,
1621) {
1622    // For each header name/value pair, there may be a value in the casemap
1623    // that corresponds to the HeaderValue. So, we iterator all the keys,
1624    // and for each one, try to pair the originally cased name with the value.
1625    //
1626    // TODO: consider adding http::HeaderMap::entries() iterator
1627    for name in headers.keys() {
1628        let mut names = orig_case.get_all(name);
1629
1630        for value in headers.get_all(name) {
1631            if let Some(orig_name) = names.next() {
1632                extend(dst, orig_name.as_ref());
1633            } else if title_case_headers {
1634                title_case(dst, name.as_str().as_bytes());
1635            } else {
1636                extend(dst, name.as_str().as_bytes());
1637            }
1638
1639            // Wanted for curl test cases that send `X-Custom-Header:\r\n`
1640            if value.is_empty() {
1641                extend(dst, b":\r\n");
1642            } else {
1643                extend(dst, b": ");
1644                extend(dst, value.as_bytes());
1645                extend(dst, b"\r\n");
1646            }
1647        }
1648    }
1649}
1650
1651#[cfg(feature = "client")]
1652struct FastWrite<'a>(&'a mut Vec<u8>);
1653
1654#[cfg(feature = "client")]
1655impl fmt::Write for FastWrite<'_> {
1656    #[inline]
1657    fn write_str(&mut self, s: &str) -> fmt::Result {
1658        extend(self.0, s.as_bytes());
1659        Ok(())
1660    }
1661
1662    #[inline]
1663    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
1664        fmt::write(self, args)
1665    }
1666}
1667
1668#[inline]
1669fn extend(dst: &mut Vec<u8>, data: &[u8]) {
1670    dst.extend_from_slice(data);
1671}
1672
1673#[cfg(test)]
1674mod tests {
1675    use bytes::BytesMut;
1676
1677    use super::*;
1678
1679    #[cfg(feature = "server")]
1680    #[test]
1681    fn test_parse_request() {
1682        let _ = pretty_env_logger::try_init();
1683        let mut raw = BytesMut::from("GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1684        let mut method = None;
1685        let msg = Server::parse(
1686            &mut raw,
1687            ParseContext {
1688                cached_headers: &mut None,
1689                req_method: &mut method,
1690                h1_parser_config: Default::default(),
1691                h1_max_headers: None,
1692                preserve_header_case: false,
1693                #[cfg(feature = "ffi")]
1694                preserve_header_order: false,
1695                h09_responses: false,
1696                #[cfg(feature = "client")]
1697                on_informational: &mut None,
1698            },
1699        )
1700        .unwrap()
1701        .unwrap();
1702        assert_eq!(raw.len(), 0);
1703        assert_eq!(msg.head.subject.0, crate::Method::GET);
1704        assert_eq!(msg.head.subject.1, "/echo");
1705        assert_eq!(msg.head.version, crate::Version::HTTP_11);
1706        assert_eq!(msg.head.headers.len(), 1);
1707        assert_eq!(msg.head.headers["Host"], "hyper.rs");
1708        assert_eq!(method, Some(crate::Method::GET));
1709    }
1710
1711    #[test]
1712    fn test_parse_response() {
1713        let _ = pretty_env_logger::try_init();
1714        let mut raw = BytesMut::from("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1715        let ctx = ParseContext {
1716            cached_headers: &mut None,
1717            req_method: &mut Some(crate::Method::GET),
1718            h1_parser_config: Default::default(),
1719            h1_max_headers: None,
1720            preserve_header_case: false,
1721            #[cfg(feature = "ffi")]
1722            preserve_header_order: false,
1723            h09_responses: false,
1724            #[cfg(feature = "client")]
1725            on_informational: &mut None,
1726        };
1727        let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1728        assert_eq!(raw.len(), 0);
1729        assert_eq!(msg.head.subject, crate::StatusCode::OK);
1730        assert_eq!(msg.head.version, crate::Version::HTTP_11);
1731        assert_eq!(msg.head.headers.len(), 1);
1732        assert_eq!(msg.head.headers["Content-Length"], "0");
1733    }
1734
1735    #[cfg(feature = "server")]
1736    #[test]
1737    fn test_parse_request_errors() {
1738        let mut raw = BytesMut::from("GET htt:p// HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1739        let ctx = ParseContext {
1740            cached_headers: &mut None,
1741            req_method: &mut None,
1742            h1_parser_config: Default::default(),
1743            h1_max_headers: None,
1744            preserve_header_case: false,
1745            #[cfg(feature = "ffi")]
1746            preserve_header_order: false,
1747            h09_responses: false,
1748            #[cfg(feature = "client")]
1749            on_informational: &mut None,
1750        };
1751        Server::parse(&mut raw, ctx).unwrap_err();
1752    }
1753
1754    const H09_RESPONSE: &str = "Baguettes are super delicious, don't you agree?";
1755
1756    #[test]
1757    fn test_parse_response_h09_allowed() {
1758        let _ = pretty_env_logger::try_init();
1759        let mut raw = BytesMut::from(H09_RESPONSE);
1760        let ctx = ParseContext {
1761            cached_headers: &mut None,
1762            req_method: &mut Some(crate::Method::GET),
1763            h1_parser_config: Default::default(),
1764            h1_max_headers: None,
1765            preserve_header_case: false,
1766            #[cfg(feature = "ffi")]
1767            preserve_header_order: false,
1768            h09_responses: true,
1769            #[cfg(feature = "client")]
1770            on_informational: &mut None,
1771        };
1772        let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1773        assert_eq!(raw, H09_RESPONSE);
1774        assert_eq!(msg.head.subject, crate::StatusCode::OK);
1775        assert_eq!(msg.head.version, crate::Version::HTTP_09);
1776        assert_eq!(msg.head.headers.len(), 0);
1777    }
1778
1779    #[test]
1780    fn test_parse_response_h09_rejected() {
1781        let _ = pretty_env_logger::try_init();
1782        let mut raw = BytesMut::from(H09_RESPONSE);
1783        let ctx = ParseContext {
1784            cached_headers: &mut None,
1785            req_method: &mut Some(crate::Method::GET),
1786            h1_parser_config: Default::default(),
1787            h1_max_headers: None,
1788            preserve_header_case: false,
1789            #[cfg(feature = "ffi")]
1790            preserve_header_order: false,
1791            h09_responses: false,
1792            #[cfg(feature = "client")]
1793            on_informational: &mut None,
1794        };
1795        Client::parse(&mut raw, ctx).unwrap_err();
1796        assert_eq!(raw, H09_RESPONSE);
1797    }
1798
1799    const RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &str =
1800        "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\n\r\n";
1801
1802    #[test]
1803    fn test_parse_allow_response_with_spaces_before_colons() {
1804        use httparse::ParserConfig;
1805
1806        let _ = pretty_env_logger::try_init();
1807        let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1808        let mut h1_parser_config = ParserConfig::default();
1809        h1_parser_config.allow_spaces_after_header_name_in_responses(true);
1810        let ctx = ParseContext {
1811            cached_headers: &mut None,
1812            req_method: &mut Some(crate::Method::GET),
1813            h1_parser_config,
1814            h1_max_headers: None,
1815            preserve_header_case: false,
1816            #[cfg(feature = "ffi")]
1817            preserve_header_order: false,
1818            h09_responses: false,
1819            #[cfg(feature = "client")]
1820            on_informational: &mut None,
1821        };
1822        let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1823        assert_eq!(raw.len(), 0);
1824        assert_eq!(msg.head.subject, crate::StatusCode::OK);
1825        assert_eq!(msg.head.version, crate::Version::HTTP_11);
1826        assert_eq!(msg.head.headers.len(), 1);
1827        assert_eq!(msg.head.headers["Access-Control-Allow-Credentials"], "true");
1828    }
1829
1830    #[test]
1831    fn test_parse_reject_response_with_spaces_before_colons() {
1832        let _ = pretty_env_logger::try_init();
1833        let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1834        let ctx = ParseContext {
1835            cached_headers: &mut None,
1836            req_method: &mut Some(crate::Method::GET),
1837            h1_parser_config: Default::default(),
1838            h1_max_headers: None,
1839            preserve_header_case: false,
1840            #[cfg(feature = "ffi")]
1841            preserve_header_order: false,
1842            h09_responses: false,
1843            #[cfg(feature = "client")]
1844            on_informational: &mut None,
1845        };
1846        Client::parse(&mut raw, ctx).unwrap_err();
1847    }
1848
1849    const REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE: &str =
1850        "GET  /echo  HTTP/1.1\r\nHost: hyper.rs\r\n\r\n";
1851
1852    #[cfg(feature = "server")]
1853    #[test]
1854    fn test_parse_allow_request_with_multiple_spaces_in_request_line() {
1855        use httparse::ParserConfig;
1856
1857        let _ = pretty_env_logger::try_init();
1858        let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1859        let mut h1_parser_config = ParserConfig::default();
1860        h1_parser_config.allow_multiple_spaces_in_request_line_delimiters(true);
1861        let mut method = None;
1862        let ctx = ParseContext {
1863            cached_headers: &mut None,
1864            req_method: &mut method,
1865            h1_parser_config,
1866            h1_max_headers: None,
1867            preserve_header_case: false,
1868            #[cfg(feature = "ffi")]
1869            preserve_header_order: false,
1870            h09_responses: false,
1871            #[cfg(feature = "client")]
1872            on_informational: &mut None,
1873        };
1874        let msg = Server::parse(&mut raw, ctx).unwrap().unwrap();
1875        assert_eq!(raw.len(), 0);
1876        assert_eq!(msg.head.subject.0, crate::Method::GET);
1877        assert_eq!(msg.head.subject.1, "/echo");
1878        assert_eq!(msg.head.version, crate::Version::HTTP_11);
1879        assert_eq!(msg.head.headers.len(), 1);
1880        assert_eq!(msg.head.headers["Host"], "hyper.rs");
1881        assert_eq!(method, Some(crate::Method::GET));
1882    }
1883
1884    #[cfg(feature = "server")]
1885    #[test]
1886    fn test_parse_reject_request_with_multiple_spaces_in_request_line() {
1887        let _ = pretty_env_logger::try_init();
1888        let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1889        let ctx = ParseContext {
1890            cached_headers: &mut None,
1891            req_method: &mut None,
1892            h1_parser_config: Default::default(),
1893            h1_max_headers: None,
1894            preserve_header_case: false,
1895            #[cfg(feature = "ffi")]
1896            preserve_header_order: false,
1897            h09_responses: false,
1898            #[cfg(feature = "client")]
1899            on_informational: &mut None,
1900        };
1901        Server::parse(&mut raw, ctx).unwrap_err();
1902    }
1903
1904    #[cfg(feature = "server")]
1905    #[test]
1906    fn test_parse_preserve_header_case_in_request() {
1907        let mut raw =
1908            BytesMut::from("GET / HTTP/1.1\r\nHost: hyper.rs\r\nX-BREAD: baguette\r\n\r\n");
1909        let ctx = ParseContext {
1910            cached_headers: &mut None,
1911            req_method: &mut None,
1912            h1_parser_config: Default::default(),
1913            h1_max_headers: None,
1914            preserve_header_case: true,
1915            #[cfg(feature = "ffi")]
1916            preserve_header_order: false,
1917            h09_responses: false,
1918            #[cfg(feature = "client")]
1919            on_informational: &mut None,
1920        };
1921        let parsed_message = Server::parse(&mut raw, ctx).unwrap().unwrap();
1922        let orig_headers = parsed_message
1923            .head
1924            .extensions
1925            .get::<HeaderCaseMap>()
1926            .unwrap();
1927        assert_eq!(
1928            orig_headers
1929                .get_all_internal(&HeaderName::from_static("host"))
1930                .collect::<Vec<_>>(),
1931            vec![&Bytes::from("Host")]
1932        );
1933        assert_eq!(
1934            orig_headers
1935                .get_all_internal(&HeaderName::from_static("x-bread"))
1936                .collect::<Vec<_>>(),
1937            vec![&Bytes::from("X-BREAD")]
1938        );
1939    }
1940
1941    #[cfg(feature = "server")]
1942    #[test]
1943    fn test_decoder_request() {
1944        fn parse(s: &str) -> ParsedMessage<RequestLine> {
1945            let mut bytes = BytesMut::from(s);
1946            Server::parse(
1947                &mut bytes,
1948                ParseContext {
1949                    cached_headers: &mut None,
1950                    req_method: &mut None,
1951                    h1_parser_config: Default::default(),
1952                    h1_max_headers: None,
1953                    preserve_header_case: false,
1954                    #[cfg(feature = "ffi")]
1955                    preserve_header_order: false,
1956                    h09_responses: false,
1957                    #[cfg(feature = "client")]
1958                    on_informational: &mut None,
1959                },
1960            )
1961            .expect("parse ok")
1962            .expect("parse complete")
1963        }
1964
1965        fn parse_err(s: &str, comment: &str) -> crate::error::Parse {
1966            let mut bytes = BytesMut::from(s);
1967            Server::parse(
1968                &mut bytes,
1969                ParseContext {
1970                    cached_headers: &mut None,
1971                    req_method: &mut None,
1972                    h1_parser_config: Default::default(),
1973                    h1_max_headers: None,
1974                    preserve_header_case: false,
1975                    #[cfg(feature = "ffi")]
1976                    preserve_header_order: false,
1977                    h09_responses: false,
1978                    #[cfg(feature = "client")]
1979                    on_informational: &mut None,
1980                },
1981            )
1982            .expect_err(comment)
1983        }
1984
1985        // no length or transfer-encoding means 0-length body
1986        assert_eq!(
1987            parse(
1988                "\
1989                 GET / HTTP/1.1\r\n\
1990                 \r\n\
1991                 "
1992            )
1993            .decode,
1994            DecodedLength::ZERO
1995        );
1996
1997        assert_eq!(
1998            parse(
1999                "\
2000                 POST / HTTP/1.1\r\n\
2001                 \r\n\
2002                 "
2003            )
2004            .decode,
2005            DecodedLength::ZERO
2006        );
2007
2008        // transfer-encoding: chunked
2009        assert_eq!(
2010            parse(
2011                "\
2012                 POST / HTTP/1.1\r\n\
2013                 transfer-encoding: chunked\r\n\
2014                 \r\n\
2015                 "
2016            )
2017            .decode,
2018            DecodedLength::CHUNKED
2019        );
2020
2021        assert_eq!(
2022            parse(
2023                "\
2024                 POST / HTTP/1.1\r\n\
2025                 transfer-encoding: gzip, chunked\r\n\
2026                 \r\n\
2027                 "
2028            )
2029            .decode,
2030            DecodedLength::CHUNKED
2031        );
2032
2033        assert_eq!(
2034            parse(
2035                "\
2036                 POST / HTTP/1.1\r\n\
2037                 transfer-encoding: gzip\r\n\
2038                 transfer-encoding: chunked\r\n\
2039                 \r\n\
2040                 "
2041            )
2042            .decode,
2043            DecodedLength::CHUNKED
2044        );
2045
2046        // content-length
2047        assert_eq!(
2048            parse(
2049                "\
2050                 POST / HTTP/1.1\r\n\
2051                 content-length: 10\r\n\
2052                 \r\n\
2053                 "
2054            )
2055            .decode,
2056            DecodedLength::new(10)
2057        );
2058
2059        // transfer-encoding and content-length = chunked
2060        let msg = parse(
2061            "\
2062             POST / HTTP/1.1\r\n\
2063             content-length: 10\r\n\
2064             transfer-encoding: chunked\r\n\
2065             \r\n\
2066             ",
2067        );
2068        assert_eq!(msg.decode, DecodedLength::CHUNKED);
2069        assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2070        assert!(!msg.keep_alive);
2071
2072        let msg = parse(
2073            "\
2074             POST / HTTP/1.1\r\n\
2075             transfer-encoding: chunked\r\n\
2076             content-length: 10\r\n\
2077             \r\n\
2078             ",
2079        );
2080        assert_eq!(msg.decode, DecodedLength::CHUNKED);
2081        assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2082        assert!(!msg.keep_alive);
2083
2084        let msg = parse(
2085            "\
2086             POST / HTTP/1.1\r\n\
2087             transfer-encoding: gzip\r\n\
2088             content-length: 10\r\n\
2089             transfer-encoding: chunked\r\n\
2090             \r\n\
2091             ",
2092        );
2093        assert_eq!(msg.decode, DecodedLength::CHUNKED);
2094        assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2095        assert!(!msg.keep_alive);
2096
2097        let msg = parse(
2098            "\
2099             POST / HTTP/1.1\r\n\
2100             connection: keep-alive\r\n\
2101             content-length: 10\r\n\
2102             transfer-encoding: chunked\r\n\
2103             \r\n\
2104             ",
2105        );
2106        assert_eq!(msg.decode, DecodedLength::CHUNKED);
2107        assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2108        assert!(!msg.keep_alive);
2109
2110        // multiple content-lengths of same value are fine
2111        assert_eq!(
2112            parse(
2113                "\
2114                 POST / HTTP/1.1\r\n\
2115                 content-length: 10\r\n\
2116                 content-length: 10\r\n\
2117                 \r\n\
2118                 "
2119            )
2120            .decode,
2121            DecodedLength::new(10)
2122        );
2123
2124        // multiple content-lengths with different values is an error
2125        parse_err(
2126            "\
2127             POST / HTTP/1.1\r\n\
2128             content-length: 10\r\n\
2129             content-length: 11\r\n\
2130             \r\n\
2131             ",
2132            "multiple content-lengths",
2133        );
2134
2135        // content-length with prefix is not allowed
2136        parse_err(
2137            "\
2138             POST / HTTP/1.1\r\n\
2139             content-length: +10\r\n\
2140             \r\n\
2141             ",
2142            "prefixed content-length",
2143        );
2144
2145        // transfer-encoding that isn't chunked is an error
2146        parse_err(
2147            "\
2148             POST / HTTP/1.1\r\n\
2149             transfer-encoding: gzip\r\n\
2150             \r\n\
2151             ",
2152            "transfer-encoding but not chunked",
2153        );
2154
2155        parse_err(
2156            "\
2157             POST / HTTP/1.1\r\n\
2158             transfer-encoding: chunked, gzip\r\n\
2159             \r\n\
2160             ",
2161            "transfer-encoding doesn't end in chunked",
2162        );
2163
2164        parse_err(
2165            "\
2166             POST / HTTP/1.1\r\n\
2167             transfer-encoding: chunked\r\n\
2168             transfer-encoding: afterlol\r\n\
2169             \r\n\
2170             ",
2171            "transfer-encoding multiple lines doesn't end in chunked",
2172        );
2173
2174        // http/1.0
2175
2176        assert_eq!(
2177            parse(
2178                "\
2179                 POST / HTTP/1.0\r\n\
2180                 content-length: 10\r\n\
2181                 \r\n\
2182                 "
2183            )
2184            .decode,
2185            DecodedLength::new(10)
2186        );
2187
2188        // 1.0 doesn't understand chunked, so its an error
2189        parse_err(
2190            "\
2191             POST / HTTP/1.0\r\n\
2192             transfer-encoding: chunked\r\n\
2193             \r\n\
2194             ",
2195            "1.0 chunked",
2196        );
2197    }
2198
2199    #[test]
2200    fn test_decoder_response() {
2201        fn parse(s: &str) -> ParsedMessage<StatusCode> {
2202            parse_with_method(s, Method::GET)
2203        }
2204
2205        fn parse_ignores(s: &str) {
2206            let mut bytes = BytesMut::from(s);
2207            assert!(Client::parse(
2208                &mut bytes,
2209                ParseContext {
2210                    cached_headers: &mut None,
2211                    req_method: &mut Some(Method::GET),
2212                    h1_parser_config: Default::default(),
2213                    h1_max_headers: None,
2214                    preserve_header_case: false,
2215                    #[cfg(feature = "ffi")]
2216                    preserve_header_order: false,
2217                    h09_responses: false,
2218                    #[cfg(feature = "client")]
2219                    on_informational: &mut None,
2220                }
2221            )
2222            .expect("parse ok")
2223            .is_none())
2224        }
2225
2226        fn parse_with_method(s: &str, m: Method) -> ParsedMessage<StatusCode> {
2227            let mut bytes = BytesMut::from(s);
2228            Client::parse(
2229                &mut bytes,
2230                ParseContext {
2231                    cached_headers: &mut None,
2232                    req_method: &mut Some(m),
2233                    h1_parser_config: Default::default(),
2234                    h1_max_headers: None,
2235                    preserve_header_case: false,
2236                    #[cfg(feature = "ffi")]
2237                    preserve_header_order: false,
2238                    h09_responses: false,
2239                    #[cfg(feature = "client")]
2240                    on_informational: &mut None,
2241                },
2242            )
2243            .expect("parse ok")
2244            .expect("parse complete")
2245        }
2246
2247        fn parse_err(s: &str) -> crate::error::Parse {
2248            let mut bytes = BytesMut::from(s);
2249            Client::parse(
2250                &mut bytes,
2251                ParseContext {
2252                    cached_headers: &mut None,
2253                    req_method: &mut Some(Method::GET),
2254                    h1_parser_config: Default::default(),
2255                    h1_max_headers: None,
2256                    preserve_header_case: false,
2257                    #[cfg(feature = "ffi")]
2258                    preserve_header_order: false,
2259                    h09_responses: false,
2260                    #[cfg(feature = "client")]
2261                    on_informational: &mut None,
2262                },
2263            )
2264            .expect_err("parse should err")
2265        }
2266
2267        // no content-length or transfer-encoding means close-delimited
2268        assert_eq!(
2269            parse(
2270                "\
2271                 HTTP/1.1 200 OK\r\n\
2272                 \r\n\
2273                 "
2274            )
2275            .decode,
2276            DecodedLength::CLOSE_DELIMITED
2277        );
2278
2279        // 204 and 304 never have a body
2280        assert_eq!(
2281            parse(
2282                "\
2283                 HTTP/1.1 204 No Content\r\n\
2284                 \r\n\
2285                 "
2286            )
2287            .decode,
2288            DecodedLength::ZERO
2289        );
2290
2291        assert_eq!(
2292            parse(
2293                "\
2294                 HTTP/1.1 304 Not Modified\r\n\
2295                 \r\n\
2296                 "
2297            )
2298            .decode,
2299            DecodedLength::ZERO
2300        );
2301
2302        // content-length
2303        assert_eq!(
2304            parse(
2305                "\
2306                 HTTP/1.1 200 OK\r\n\
2307                 content-length: 8\r\n\
2308                 \r\n\
2309                 "
2310            )
2311            .decode,
2312            DecodedLength::new(8)
2313        );
2314
2315        assert_eq!(
2316            parse(
2317                "\
2318                 HTTP/1.1 200 OK\r\n\
2319                 content-length: 8\r\n\
2320                 content-length: 8\r\n\
2321                 \r\n\
2322                 "
2323            )
2324            .decode,
2325            DecodedLength::new(8)
2326        );
2327
2328        parse_err(
2329            "\
2330             HTTP/1.1 200 OK\r\n\
2331             content-length: 8\r\n\
2332             content-length: 9\r\n\
2333             \r\n\
2334             ",
2335        );
2336
2337        parse_err(
2338            "\
2339             HTTP/1.1 200 OK\r\n\
2340             content-length: +8\r\n\
2341             \r\n\
2342             ",
2343        );
2344
2345        // transfer-encoding: chunked
2346        assert_eq!(
2347            parse(
2348                "\
2349                 HTTP/1.1 200 OK\r\n\
2350                 transfer-encoding: chunked\r\n\
2351                 \r\n\
2352                 "
2353            )
2354            .decode,
2355            DecodedLength::CHUNKED
2356        );
2357
2358        // transfer-encoding not-chunked is close-delimited
2359        assert_eq!(
2360            parse(
2361                "\
2362                 HTTP/1.1 200 OK\r\n\
2363                 transfer-encoding: yolo\r\n\
2364                 \r\n\
2365                 "
2366            )
2367            .decode,
2368            DecodedLength::CLOSE_DELIMITED
2369        );
2370
2371        // transfer-encoding and content-length = chunked
2372        assert_eq!(
2373            parse(
2374                "\
2375                 HTTP/1.1 200 OK\r\n\
2376                 content-length: 10\r\n\
2377                 transfer-encoding: chunked\r\n\
2378                 \r\n\
2379                 "
2380            )
2381            .decode,
2382            DecodedLength::CHUNKED
2383        );
2384
2385        // HEAD can have content-length, but not body
2386        assert_eq!(
2387            parse_with_method(
2388                "\
2389                 HTTP/1.1 200 OK\r\n\
2390                 content-length: 8\r\n\
2391                 \r\n\
2392                 ",
2393                Method::HEAD
2394            )
2395            .decode,
2396            DecodedLength::ZERO
2397        );
2398
2399        // CONNECT with 200 never has body
2400        {
2401            let msg = parse_with_method(
2402                "\
2403                 HTTP/1.1 200 OK\r\n\
2404                 \r\n\
2405                 ",
2406                Method::CONNECT,
2407            );
2408            assert_eq!(msg.decode, DecodedLength::ZERO);
2409            assert!(!msg.keep_alive, "should be upgrade");
2410            assert!(msg.wants_upgrade, "should be upgrade");
2411        }
2412
2413        // CONNECT receiving non 200 can have a body
2414        assert_eq!(
2415            parse_with_method(
2416                "\
2417                 HTTP/1.1 400 Bad Request\r\n\
2418                 \r\n\
2419                 ",
2420                Method::CONNECT
2421            )
2422            .decode,
2423            DecodedLength::CLOSE_DELIMITED
2424        );
2425
2426        // 1xx status codes
2427        parse_ignores(
2428            "\
2429             HTTP/1.1 100 Continue\r\n\
2430             \r\n\
2431             ",
2432        );
2433
2434        parse_ignores(
2435            "\
2436             HTTP/1.1 103 Early Hints\r\n\
2437             \r\n\
2438             ",
2439        );
2440
2441        // 101 upgrade not supported yet
2442        {
2443            let msg = parse(
2444                "\
2445                 HTTP/1.1 101 Switching Protocols\r\n\
2446                 \r\n\
2447                 ",
2448            );
2449            assert_eq!(msg.decode, DecodedLength::ZERO);
2450            assert!(!msg.keep_alive, "should be last");
2451            assert!(msg.wants_upgrade, "should be upgrade");
2452        }
2453
2454        // http/1.0
2455        assert_eq!(
2456            parse(
2457                "\
2458                 HTTP/1.0 200 OK\r\n\
2459                 \r\n\
2460                 "
2461            )
2462            .decode,
2463            DecodedLength::CLOSE_DELIMITED
2464        );
2465
2466        // 1.0 doesn't understand chunked
2467        parse_err(
2468            "\
2469             HTTP/1.0 200 OK\r\n\
2470             transfer-encoding: chunked\r\n\
2471             \r\n\
2472             ",
2473        );
2474
2475        // keep-alive
2476        assert!(
2477            parse(
2478                "\
2479                 HTTP/1.1 200 OK\r\n\
2480                 content-length: 0\r\n\
2481                 \r\n\
2482                 "
2483            )
2484            .keep_alive,
2485            "HTTP/1.1 keep-alive is default"
2486        );
2487
2488        assert!(
2489            !parse(
2490                "\
2491                 HTTP/1.1 200 OK\r\n\
2492                 content-length: 0\r\n\
2493                 connection: foo, close, bar\r\n\
2494                 \r\n\
2495                 "
2496            )
2497            .keep_alive,
2498            "connection close is always close"
2499        );
2500
2501        assert!(
2502            !parse(
2503                "\
2504                 HTTP/1.0 200 OK\r\n\
2505                 content-length: 0\r\n\
2506                 \r\n\
2507                 "
2508            )
2509            .keep_alive,
2510            "HTTP/1.0 close is default"
2511        );
2512
2513        assert!(
2514            parse(
2515                "\
2516                 HTTP/1.0 200 OK\r\n\
2517                 content-length: 0\r\n\
2518                 connection: foo, keep-alive, bar\r\n\
2519                 \r\n\
2520                 "
2521            )
2522            .keep_alive,
2523            "connection keep-alive is always keep-alive"
2524        );
2525    }
2526
2527    #[cfg(feature = "client")]
2528    #[test]
2529    fn test_client_obs_fold_line() {
2530        fn unfold(src: &str) -> String {
2531            let mut buf = src.as_bytes().to_vec();
2532            let mut idx = HeaderIndices {
2533                name: (0, 0),
2534                value: (0, buf.len()),
2535            };
2536            Client::obs_fold_line(&mut buf, &mut idx);
2537            String::from_utf8(buf[idx.value.0..idx.value.1].to_vec()).unwrap()
2538        }
2539
2540        assert_eq!(unfold("a normal line"), "a normal line",);
2541
2542        assert_eq!(unfold("obs\r\n fold\r\n\t line"), "obs fold line",);
2543    }
2544
2545    #[test]
2546    fn test_client_request_encode_title_case() {
2547        use crate::proto::BodyLength;
2548        use http::header::HeaderValue;
2549
2550        let mut head = MessageHead::default();
2551        head.headers
2552            .insert("content-length", HeaderValue::from_static("10"));
2553        head.headers
2554            .insert("content-type", HeaderValue::from_static("application/json"));
2555        head.headers.insert("*-*", HeaderValue::from_static("o_o"));
2556
2557        let mut vec = Vec::new();
2558        Client::encode(
2559            Encode {
2560                head: &mut head,
2561                body: Some(BodyLength::Known(10)),
2562                #[cfg(feature = "server")]
2563                keep_alive: true,
2564                req_method: &mut None,
2565                title_case_headers: true,
2566                #[cfg(feature = "server")]
2567                date_header: true,
2568            },
2569            &mut vec,
2570        )
2571        .unwrap();
2572
2573        assert_eq!(vec, b"GET / HTTP/1.1\r\nContent-Length: 10\r\nContent-Type: application/json\r\n*-*: o_o\r\n\r\n".to_vec());
2574    }
2575
2576    #[test]
2577    fn test_client_request_encode_orig_case() {
2578        use crate::proto::BodyLength;
2579        use http::header::{HeaderValue, CONTENT_LENGTH};
2580
2581        let mut head = MessageHead::default();
2582        head.headers
2583            .insert("content-length", HeaderValue::from_static("10"));
2584        head.headers
2585            .insert("content-type", HeaderValue::from_static("application/json"));
2586
2587        let mut orig_headers = HeaderCaseMap::default();
2588        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2589        head.extensions.insert(orig_headers);
2590
2591        let mut vec = Vec::new();
2592        Client::encode(
2593            Encode {
2594                head: &mut head,
2595                body: Some(BodyLength::Known(10)),
2596                #[cfg(feature = "server")]
2597                keep_alive: true,
2598                req_method: &mut None,
2599                title_case_headers: false,
2600                #[cfg(feature = "server")]
2601                date_header: true,
2602            },
2603            &mut vec,
2604        )
2605        .unwrap();
2606
2607        assert_eq!(
2608            &*vec,
2609            b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\n\r\n"
2610                .as_ref(),
2611        );
2612    }
2613    #[test]
2614    fn test_client_request_encode_orig_and_title_case() {
2615        use crate::proto::BodyLength;
2616        use http::header::{HeaderValue, CONTENT_LENGTH};
2617
2618        let mut head = MessageHead::default();
2619        head.headers
2620            .insert("content-length", HeaderValue::from_static("10"));
2621        head.headers
2622            .insert("content-type", HeaderValue::from_static("application/json"));
2623
2624        let mut orig_headers = HeaderCaseMap::default();
2625        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2626        head.extensions.insert(orig_headers);
2627
2628        let mut vec = Vec::new();
2629        Client::encode(
2630            Encode {
2631                head: &mut head,
2632                body: Some(BodyLength::Known(10)),
2633                #[cfg(feature = "server")]
2634                keep_alive: true,
2635                req_method: &mut None,
2636                title_case_headers: true,
2637                #[cfg(feature = "server")]
2638                date_header: true,
2639            },
2640            &mut vec,
2641        )
2642        .unwrap();
2643
2644        assert_eq!(
2645            &*vec,
2646            b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\n\r\n"
2647                .as_ref(),
2648        );
2649    }
2650
2651    #[cfg(feature = "server")]
2652    #[test]
2653    fn test_server_encode_connect_method() {
2654        let mut head = MessageHead::default();
2655
2656        let mut vec = Vec::new();
2657        let encoder = Server::encode(
2658            Encode {
2659                head: &mut head,
2660                body: None,
2661                keep_alive: true,
2662                req_method: &mut Some(Method::CONNECT),
2663                title_case_headers: false,
2664                date_header: true,
2665            },
2666            &mut vec,
2667        )
2668        .unwrap();
2669
2670        assert!(encoder.is_last());
2671    }
2672
2673    #[cfg(feature = "server")]
2674    #[test]
2675    fn test_server_response_encode_title_case() {
2676        use crate::proto::BodyLength;
2677        use http::header::HeaderValue;
2678
2679        let mut head = MessageHead::default();
2680        head.headers
2681            .insert("content-length", HeaderValue::from_static("10"));
2682        head.headers
2683            .insert("content-type", HeaderValue::from_static("application/json"));
2684        head.headers
2685            .insert("weird--header", HeaderValue::from_static(""));
2686
2687        let mut vec = Vec::new();
2688        Server::encode(
2689            Encode {
2690                head: &mut head,
2691                body: Some(BodyLength::Known(10)),
2692                keep_alive: true,
2693                req_method: &mut None,
2694                title_case_headers: true,
2695                date_header: true,
2696            },
2697            &mut vec,
2698        )
2699        .unwrap();
2700
2701        let expected_response =
2702            b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: application/json\r\nWeird--Header: \r\n";
2703
2704        assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2705    }
2706
2707    #[cfg(feature = "server")]
2708    #[test]
2709    fn test_server_response_encode_orig_case() {
2710        use crate::proto::BodyLength;
2711        use http::header::{HeaderValue, CONTENT_LENGTH};
2712
2713        let mut head = MessageHead::default();
2714        head.headers
2715            .insert("content-length", HeaderValue::from_static("10"));
2716        head.headers
2717            .insert("content-type", HeaderValue::from_static("application/json"));
2718
2719        let mut orig_headers = HeaderCaseMap::default();
2720        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2721        head.extensions.insert(orig_headers);
2722
2723        let mut vec = Vec::new();
2724        Server::encode(
2725            Encode {
2726                head: &mut head,
2727                body: Some(BodyLength::Known(10)),
2728                keep_alive: true,
2729                req_method: &mut None,
2730                title_case_headers: false,
2731                date_header: true,
2732            },
2733            &mut vec,
2734        )
2735        .unwrap();
2736
2737        let expected_response =
2738            b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\ndate: ";
2739
2740        assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2741    }
2742
2743    #[cfg(feature = "server")]
2744    #[test]
2745    fn test_server_response_encode_orig_and_title_case() {
2746        use crate::proto::BodyLength;
2747        use http::header::{HeaderValue, CONTENT_LENGTH};
2748
2749        let mut head = MessageHead::default();
2750        head.headers
2751            .insert("content-length", HeaderValue::from_static("10"));
2752        head.headers
2753            .insert("content-type", HeaderValue::from_static("application/json"));
2754
2755        let mut orig_headers = HeaderCaseMap::default();
2756        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2757        head.extensions.insert(orig_headers);
2758
2759        let mut vec = Vec::new();
2760        Server::encode(
2761            Encode {
2762                head: &mut head,
2763                body: Some(BodyLength::Known(10)),
2764                keep_alive: true,
2765                req_method: &mut None,
2766                title_case_headers: true,
2767                date_header: true,
2768            },
2769            &mut vec,
2770        )
2771        .unwrap();
2772
2773        // this will also test that the date does exist
2774        let expected_response =
2775            b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\nDate: ";
2776
2777        assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2778    }
2779
2780    #[cfg(feature = "server")]
2781    #[test]
2782    fn test_disabled_date_header() {
2783        use crate::proto::BodyLength;
2784        use http::header::{HeaderValue, CONTENT_LENGTH};
2785
2786        let mut head = MessageHead::default();
2787        head.headers
2788            .insert("content-length", HeaderValue::from_static("10"));
2789        head.headers
2790            .insert("content-type", HeaderValue::from_static("application/json"));
2791
2792        let mut orig_headers = HeaderCaseMap::default();
2793        orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2794        head.extensions.insert(orig_headers);
2795
2796        let mut vec = Vec::new();
2797        Server::encode(
2798            Encode {
2799                head: &mut head,
2800                body: Some(BodyLength::Known(10)),
2801                keep_alive: true,
2802                req_method: &mut None,
2803                title_case_headers: true,
2804                date_header: false,
2805            },
2806            &mut vec,
2807        )
2808        .unwrap();
2809
2810        let expected_response =
2811            b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\n\r\n";
2812
2813        assert_eq!(&vec, &expected_response);
2814    }
2815
2816    #[test]
2817    fn parse_header_htabs() {
2818        let mut bytes = BytesMut::from("HTTP/1.1 200 OK\r\nserver: hello\tworld\r\n\r\n");
2819        let parsed = Client::parse(
2820            &mut bytes,
2821            ParseContext {
2822                cached_headers: &mut None,
2823                req_method: &mut Some(Method::GET),
2824                h1_parser_config: Default::default(),
2825                h1_max_headers: None,
2826                preserve_header_case: false,
2827                #[cfg(feature = "ffi")]
2828                preserve_header_order: false,
2829                h09_responses: false,
2830                #[cfg(feature = "client")]
2831                on_informational: &mut None,
2832            },
2833        )
2834        .expect("parse ok")
2835        .expect("parse complete");
2836
2837        assert_eq!(parsed.head.headers["server"], "hello\tworld");
2838    }
2839
2840    #[cfg(feature = "server")]
2841    #[test]
2842    fn parse_too_large_headers() {
2843        fn gen_req_with_headers(num: usize) -> String {
2844            let mut req = String::from("GET / HTTP/1.1\r\n");
2845            for i in 0..num {
2846                req.push_str(&format!("key{i}: val{i}\r\n"));
2847            }
2848            req.push_str("\r\n");
2849            req
2850        }
2851        fn gen_resp_with_headers(num: usize) -> String {
2852            let mut req = String::from("HTTP/1.1 200 OK\r\n");
2853            for i in 0..num {
2854                req.push_str(&format!("key{i}: val{i}\r\n"));
2855            }
2856            req.push_str("\r\n");
2857            req
2858        }
2859        fn parse(max_headers: Option<usize>, gen_size: usize, should_success: bool) {
2860            {
2861                // server side
2862                let mut bytes = BytesMut::from(gen_req_with_headers(gen_size).as_str());
2863                let result = Server::parse(
2864                    &mut bytes,
2865                    ParseContext {
2866                        cached_headers: &mut None,
2867                        req_method: &mut None,
2868                        h1_parser_config: Default::default(),
2869                        h1_max_headers: max_headers,
2870                        preserve_header_case: false,
2871                        #[cfg(feature = "ffi")]
2872                        preserve_header_order: false,
2873                        h09_responses: false,
2874                        #[cfg(feature = "client")]
2875                        on_informational: &mut None,
2876                    },
2877                );
2878                if should_success {
2879                    result.expect("parse ok").expect("parse complete");
2880                } else {
2881                    result.expect_err("parse should err");
2882                }
2883            }
2884            {
2885                // client side
2886                let mut bytes = BytesMut::from(gen_resp_with_headers(gen_size).as_str());
2887                let result = Client::parse(
2888                    &mut bytes,
2889                    ParseContext {
2890                        cached_headers: &mut None,
2891                        req_method: &mut None,
2892                        h1_parser_config: Default::default(),
2893                        h1_max_headers: max_headers,
2894                        preserve_header_case: false,
2895                        #[cfg(feature = "ffi")]
2896                        preserve_header_order: false,
2897                        h09_responses: false,
2898                        #[cfg(feature = "client")]
2899                        on_informational: &mut None,
2900                    },
2901                );
2902                if should_success {
2903                    result.expect("parse ok").expect("parse complete");
2904                } else {
2905                    result.expect_err("parse should err");
2906                }
2907            }
2908        }
2909
2910        // check generator
2911        assert_eq!(
2912            gen_req_with_headers(0),
2913            String::from("GET / HTTP/1.1\r\n\r\n")
2914        );
2915        assert_eq!(
2916            gen_req_with_headers(1),
2917            String::from("GET / HTTP/1.1\r\nkey0: val0\r\n\r\n")
2918        );
2919        assert_eq!(
2920            gen_req_with_headers(2),
2921            String::from("GET / HTTP/1.1\r\nkey0: val0\r\nkey1: val1\r\n\r\n")
2922        );
2923        assert_eq!(
2924            gen_req_with_headers(3),
2925            String::from("GET / HTTP/1.1\r\nkey0: val0\r\nkey1: val1\r\nkey2: val2\r\n\r\n")
2926        );
2927
2928        // default max_headers is 100, so
2929        //
2930        // - less than or equal to 100, accepted
2931        //
2932        parse(None, 0, true);
2933        parse(None, 1, true);
2934        parse(None, 50, true);
2935        parse(None, 99, true);
2936        parse(None, 100, true);
2937        //
2938        // - more than 100, rejected
2939        //
2940        parse(None, 101, false);
2941        parse(None, 102, false);
2942        parse(None, 200, false);
2943
2944        // max_headers is 0, parser will reject any headers
2945        //
2946        // - without header, accepted
2947        //
2948        parse(Some(0), 0, true);
2949        //
2950        // - with header(s), rejected
2951        //
2952        parse(Some(0), 1, false);
2953        parse(Some(0), 100, false);
2954
2955        // max_headers is 200
2956        //
2957        // - less than or equal to 200, accepted
2958        //
2959        parse(Some(200), 0, true);
2960        parse(Some(200), 1, true);
2961        parse(Some(200), 100, true);
2962        parse(Some(200), 200, true);
2963        //
2964        // - more than 200, rejected
2965        //
2966        parse(Some(200), 201, false);
2967        parse(Some(200), 210, false);
2968    }
2969
2970    #[test]
2971    fn test_is_complete_fast() {
2972        let s = b"GET / HTTP/1.1\r\na: b\r\n\r\n";
2973        for n in 0..s.len() {
2974            assert!(is_complete_fast(s, n), "{:?}; {}", s, n);
2975        }
2976        let s = b"GET / HTTP/1.1\na: b\n\n";
2977        for n in 0..s.len() {
2978            assert!(is_complete_fast(s, n));
2979        }
2980
2981        // Not
2982        let s = b"GET / HTTP/1.1\r\na: b\r\n\r";
2983        for n in 0..s.len() {
2984            assert!(!is_complete_fast(s, n));
2985        }
2986        let s = b"GET / HTTP/1.1\na: b\n";
2987        for n in 0..s.len() {
2988            assert!(!is_complete_fast(s, n));
2989        }
2990    }
2991
2992    #[test]
2993    fn test_write_headers_orig_case_empty_value() {
2994        let mut headers = HeaderMap::new();
2995        let name = http::header::HeaderName::from_static("x-empty");
2996        headers.insert(&name, "".parse().expect("parse empty"));
2997        let mut orig_cases = HeaderCaseMap::default();
2998        orig_cases.insert(name, Bytes::from_static(b"X-EmptY"));
2999
3000        let mut dst = Vec::new();
3001        super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
3002
3003        assert_eq!(
3004            dst, b"X-EmptY:\r\n",
3005            "there should be no space between the colon and CRLF"
3006        );
3007    }
3008
3009    #[test]
3010    fn test_write_headers_orig_case_multiple_entries() {
3011        let mut headers = HeaderMap::new();
3012        let name = http::header::HeaderName::from_static("x-empty");
3013        headers.insert(&name, "a".parse().unwrap());
3014        headers.append(&name, "b".parse().unwrap());
3015
3016        let mut orig_cases = HeaderCaseMap::default();
3017        orig_cases.insert(name.clone(), Bytes::from_static(b"X-Empty"));
3018        orig_cases.append(name, Bytes::from_static(b"X-EMPTY"));
3019
3020        let mut dst = Vec::new();
3021        super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
3022
3023        assert_eq!(dst, b"X-Empty: a\r\nX-EMPTY: b\r\n");
3024    }
3025
3026    #[cfg(feature = "nightly")]
3027    use test::Bencher;
3028
3029    #[cfg(feature = "nightly")]
3030    #[bench]
3031    fn bench_parse_incoming(b: &mut Bencher) {
3032        let mut raw = BytesMut::from(
3033            &b"GET /super_long_uri/and_whatever?what_should_we_talk_about/\
3034            I_wonder/Hard_to_write_in_an_uri_after_all/you_have_to_make\
3035            _up_the_punctuation_yourself/how_fun_is_that?test=foo&test1=\
3036            foo1&test2=foo2&test3=foo3&test4=foo4 HTTP/1.1\r\nHost: \
3037            hyper.rs\r\nAccept: a lot of things\r\nAccept-Charset: \
3038            utf8\r\nAccept-Encoding: *\r\nAccess-Control-Allow-\
3039            Credentials: None\r\nAccess-Control-Allow-Origin: None\r\n\
3040            Access-Control-Allow-Methods: None\r\nAccess-Control-Allow-\
3041            Headers: None\r\nContent-Encoding: utf8\r\nContent-Security-\
3042            Policy: None\r\nContent-Type: text/html\r\nOrigin: hyper\
3043            \r\nSec-Websocket-Extensions: It looks super important!\r\n\
3044            Sec-Websocket-Origin: hyper\r\nSec-Websocket-Version: 4.3\r\
3045            \nStrict-Transport-Security: None\r\nUser-Agent: hyper\r\n\
3046            X-Content-Duration: None\r\nX-Content-Security-Policy: None\
3047            \r\nX-DNSPrefetch-Control: None\r\nX-Frame-Options: \
3048            Something important obviously\r\nX-Requested-With: Nothing\
3049            \r\n\r\n"[..],
3050        );
3051        let len = raw.len();
3052        let mut headers = Some(HeaderMap::new());
3053
3054        b.bytes = len as u64;
3055        b.iter(|| {
3056            let mut msg = Server::parse(
3057                &mut raw,
3058                ParseContext {
3059                    cached_headers: &mut headers,
3060                    req_method: &mut None,
3061                    h1_parser_config: Default::default(),
3062                    h1_max_headers: None,
3063                    preserve_header_case: false,
3064                    #[cfg(feature = "ffi")]
3065                    preserve_header_order: false,
3066                    h09_responses: false,
3067                    #[cfg(feature = "client")]
3068                    on_informational: &mut None,
3069                },
3070            )
3071            .unwrap()
3072            .unwrap();
3073            ::test::black_box(&msg);
3074
3075            // Remove all references pointing into BytesMut.
3076            msg.head.headers.clear();
3077            headers = Some(msg.head.headers);
3078            std::mem::take(&mut msg.head.subject);
3079
3080            restart(&mut raw, len);
3081        });
3082
3083        fn restart(b: &mut BytesMut, len: usize) {
3084            b.reserve(1);
3085            unsafe {
3086                b.set_len(len);
3087            }
3088        }
3089    }
3090
3091    #[cfg(feature = "nightly")]
3092    #[bench]
3093    fn bench_parse_short(b: &mut Bencher) {
3094        let s = &b"GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"[..];
3095        let mut raw = BytesMut::from(s);
3096        let len = raw.len();
3097        let mut headers = Some(HeaderMap::new());
3098
3099        b.bytes = len as u64;
3100        b.iter(|| {
3101            let mut msg = Server::parse(
3102                &mut raw,
3103                ParseContext {
3104                    cached_headers: &mut headers,
3105                    req_method: &mut None,
3106                    h1_parser_config: Default::default(),
3107                    h1_max_headers: None,
3108                    preserve_header_case: false,
3109                    #[cfg(feature = "ffi")]
3110                    preserve_header_order: false,
3111                    h09_responses: false,
3112                    #[cfg(feature = "client")]
3113                    on_informational: &mut None,
3114                },
3115            )
3116            .unwrap()
3117            .unwrap();
3118            ::test::black_box(&msg);
3119            msg.head.headers.clear();
3120            headers = Some(msg.head.headers);
3121            restart(&mut raw, len);
3122        });
3123
3124        fn restart(b: &mut BytesMut, len: usize) {
3125            b.reserve(1);
3126            unsafe {
3127                b.set_len(len);
3128            }
3129        }
3130    }
3131
3132    #[cfg(feature = "nightly")]
3133    #[bench]
3134    fn bench_server_encode_headers_preset(b: &mut Bencher) {
3135        use crate::proto::BodyLength;
3136        use http::header::HeaderValue;
3137
3138        let len = 108;
3139        b.bytes = len as u64;
3140
3141        let mut head = MessageHead::default();
3142        let mut headers = HeaderMap::new();
3143        headers.insert("content-length", HeaderValue::from_static("10"));
3144        headers.insert("content-type", HeaderValue::from_static("application/json"));
3145
3146        b.iter(|| {
3147            let mut vec = Vec::new();
3148            head.headers = headers.clone();
3149            Server::encode(
3150                Encode {
3151                    head: &mut head,
3152                    body: Some(BodyLength::Known(10)),
3153                    keep_alive: true,
3154                    req_method: &mut Some(Method::GET),
3155                    title_case_headers: false,
3156                    date_header: true,
3157                },
3158                &mut vec,
3159            )
3160            .unwrap();
3161            assert_eq!(vec.len(), len);
3162            ::test::black_box(vec);
3163        })
3164    }
3165
3166    #[cfg(feature = "nightly")]
3167    #[bench]
3168    fn bench_server_encode_no_headers(b: &mut Bencher) {
3169        use crate::proto::BodyLength;
3170
3171        let len = 76;
3172        b.bytes = len as u64;
3173
3174        let mut head = MessageHead::default();
3175        let mut vec = Vec::with_capacity(128);
3176
3177        b.iter(|| {
3178            Server::encode(
3179                Encode {
3180                    head: &mut head,
3181                    body: Some(BodyLength::Known(10)),
3182                    keep_alive: true,
3183                    req_method: &mut Some(Method::GET),
3184                    title_case_headers: false,
3185                    date_header: true,
3186                },
3187                &mut vec,
3188            )
3189            .unwrap();
3190            assert_eq!(vec.len(), len);
3191            ::test::black_box(&vec);
3192
3193            vec.clear();
3194        })
3195    }
3196}