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