hyper/proto/h1/
role.rs

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