hyper/proto/h1/
role.rs

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