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