hyper/proto/h1/
role.rs

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