hyper/proto/h1/
role.rs

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