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