Skip to main content

hyper/proto/h1/
role.rs

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