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