hyper/proto/h1/
role.rs

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