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 use tracing::{debug, error, trace, trace_span, warn};
12 
13 use crate::body::DecodedLength;
14 #[cfg(feature = "server")]
15 use crate::common::date;
16 use crate::error::Parse;
17 use crate::ext::HeaderCaseMap;
18 use crate::headers;
19 use crate::proto::h1::{
20     Encode, Encoder, Http1Transaction, ParseContext, ParseResult, ParsedMessage,
21 };
22 use crate::proto::{BodyLength, MessageHead, RequestHead, RequestLine};
23 
24 const MAX_HEADERS: usize = 100;
25 const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
26 
27 macro_rules! header_name {
28     ($bytes:expr) => {{
29         {
30             match HeaderName::from_bytes($bytes) {
31                 Ok(name) => name,
32                 Err(e) => maybe_panic!(e),
33             }
34         }
35     }};
36 }
37 
38 macro_rules! header_value {
39     ($bytes:expr) => {{
40         {
41             unsafe { HeaderValue::from_maybe_shared_unchecked($bytes) }
42         }
43     }};
44 }
45 
46 macro_rules! maybe_panic {
47     ($($arg:tt)*) => ({
48         let _err = ($($arg)*);
49         if cfg!(debug_assertions) {
50             panic!("{:?}", _err);
51         } else {
52             error!("Internal Hyper error, please report {:?}", _err);
53             return Err(Parse::Internal)
54         }
55     })
56 }
57 
parse_headers<T>( bytes: &mut BytesMut, ctx: ParseContext<'_>, ) -> ParseResult<T::Incoming> where T: Http1Transaction,58 pub(super) fn parse_headers<T>(
59     bytes: &mut BytesMut,
60     ctx: ParseContext<'_>,
61 ) -> ParseResult<T::Incoming>
62 where
63     T: Http1Transaction,
64 {
65     // If the buffer is empty, don't bother entering the span, it's just noise.
66     if bytes.is_empty() {
67         return Ok(None);
68     }
69 
70     let span = trace_span!("parse_headers");
71     let _s = span.enter();
72     T::parse(bytes, ctx)
73 }
74 
encode_headers<T>( enc: Encode<'_, T::Outgoing>, dst: &mut Vec<u8>, ) -> crate::Result<Encoder> where T: Http1Transaction,75 pub(super) fn encode_headers<T>(
76     enc: Encode<'_, T::Outgoing>,
77     dst: &mut Vec<u8>,
78 ) -> crate::Result<Encoder>
79 where
80     T: Http1Transaction,
81 {
82     let span = trace_span!("encode_headers");
83     let _s = span.enter();
84     T::encode(enc, dst)
85 }
86 
87 // There are 2 main roles, Client and Server.
88 
89 #[cfg(feature = "client")]
90 pub(crate) enum Client {}
91 
92 #[cfg(feature = "server")]
93 pub(crate) enum Server {}
94 
95 #[cfg(feature = "server")]
96 impl Http1Transaction for Server {
97     type Incoming = RequestLine;
98     type Outgoing = StatusCode;
99     const LOG: &'static str = "{role=server}";
100 
parse(buf: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<RequestLine>101     fn parse(buf: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<RequestLine> {
102         debug_assert!(!buf.is_empty(), "parse called with empty buf");
103 
104         let mut keep_alive;
105         let is_http_11;
106         let subject;
107         let version;
108         let len;
109         let headers_len;
110 
111         // Unsafe: both headers_indices and headers are using uninitialized memory,
112         // but we *never* read any of it until after httparse has assigned
113         // values into it. By not zeroing out the stack memory, this saves
114         // a good ~5% on pipeline benchmarks.
115         let mut headers_indices: [MaybeUninit<HeaderIndices>; MAX_HEADERS] = unsafe {
116             // SAFETY: We can go safely from MaybeUninit array to array of MaybeUninit
117             MaybeUninit::uninit().assume_init()
118         };
119         {
120             /* SAFETY: it is safe to go from MaybeUninit array to array of MaybeUninit */
121             let mut headers: [MaybeUninit<httparse::Header<'_>>; MAX_HEADERS] =
122                 unsafe { MaybeUninit::uninit().assume_init() };
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.parse_response_with_uninit_headers(
890                     &mut res,
891                     bytes,
892                     &mut headers,
893                 ) {
894                     Ok(httparse::Status::Complete(len)) => {
895                         trace!("Response.parse Complete({})", len);
896                         let status = StatusCode::from_u16(res.code.unwrap())?;
897 
898                         #[cfg(not(feature = "ffi"))]
899                         let reason = ();
900                         #[cfg(feature = "ffi")]
901                         let reason = {
902                             let reason = res.reason.unwrap();
903                             // Only save the reason phrase if it isnt the canonical reason
904                             if Some(reason) != status.canonical_reason() {
905                                 Some(Bytes::copy_from_slice(reason.as_bytes()))
906                             } else {
907                                 None
908                             }
909                         };
910 
911                         let version = if res.version.unwrap() == 1 {
912                             Version::HTTP_11
913                         } else {
914                             Version::HTTP_10
915                         };
916                         record_header_indices(bytes, &res.headers, &mut headers_indices)?;
917                         let headers_len = res.headers.len();
918                         (len, status, reason, version, headers_len)
919                     }
920                     Ok(httparse::Status::Partial) => return Ok(None),
921                     Err(httparse::Error::Version) if ctx.h09_responses => {
922                         trace!("Response.parse accepted HTTP/0.9 response");
923 
924                         #[cfg(not(feature = "ffi"))]
925                         let reason = ();
926                         #[cfg(feature = "ffi")]
927                         let reason = None;
928 
929                         (0, StatusCode::OK, reason, Version::HTTP_09, 0)
930                     }
931                     Err(e) => return Err(e.into()),
932                 }
933             };
934 
935             let slice = buf.split_to(len).freeze();
936 
937             let mut headers = ctx.cached_headers.take().unwrap_or_else(HeaderMap::new);
938 
939             let mut keep_alive = version == Version::HTTP_11;
940 
941             let mut header_case_map = if ctx.preserve_header_case {
942                 Some(HeaderCaseMap::default())
943             } else {
944                 None
945             };
946 
947             headers.reserve(headers_len);
948             for header in &headers_indices[..headers_len] {
949                 // SAFETY: array is valid up to `headers_len`
950                 let header = unsafe { &*header.as_ptr() };
951                 let name = header_name!(&slice[header.name.0..header.name.1]);
952                 let value = header_value!(slice.slice(header.value.0..header.value.1));
953 
954                 if let header::CONNECTION = name {
955                     // keep_alive was previously set to default for Version
956                     if keep_alive {
957                         // HTTP/1.1
958                         keep_alive = !headers::connection_close(&value);
959                     } else {
960                         // HTTP/1.0
961                         keep_alive = headers::connection_keep_alive(&value);
962                     }
963                 }
964 
965                 if let Some(ref mut header_case_map) = header_case_map {
966                     header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
967                 }
968 
969                 headers.append(name, value);
970             }
971 
972             let mut extensions = http::Extensions::default();
973 
974             if let Some(header_case_map) = header_case_map {
975                 extensions.insert(header_case_map);
976             }
977 
978             #[cfg(feature = "ffi")]
979             if let Some(reason) = reason {
980                 extensions.insert(crate::ffi::ReasonPhrase(reason));
981             }
982             #[cfg(not(feature = "ffi"))]
983             drop(reason);
984 
985             #[cfg(feature = "ffi")]
986             if ctx.raw_headers {
987                 extensions.insert(crate::ffi::RawHeaders(crate::ffi::hyper_buf(slice)));
988             }
989 
990             let head = MessageHead {
991                 version,
992                 subject: status,
993                 headers,
994                 extensions,
995             };
996             if let Some((decode, is_upgrade)) = Client::decoder(&head, ctx.req_method)? {
997                 return Ok(Some(ParsedMessage {
998                     head,
999                     decode,
1000                     expect_continue: false,
1001                     // a client upgrade means the connection can't be used
1002                     // again, as it is definitely upgrading.
1003                     keep_alive: keep_alive && !is_upgrade,
1004                     wants_upgrade: is_upgrade,
1005                 }));
1006             }
1007 
1008             #[cfg(feature = "ffi")]
1009             if head.subject.is_informational() {
1010                 if let Some(callback) = ctx.on_informational {
1011                     callback.call(head.into_response(crate::Body::empty()));
1012                 }
1013             }
1014 
1015             // Parsing a 1xx response could have consumed the buffer, check if
1016             // it is empty now...
1017             if buf.is_empty() {
1018                 return Ok(None);
1019             }
1020         }
1021     }
1022 
encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder>1023     fn encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder> {
1024         trace!(
1025             "Client::encode method={:?}, body={:?}",
1026             msg.head.subject.0,
1027             msg.body
1028         );
1029 
1030         *msg.req_method = Some(msg.head.subject.0.clone());
1031 
1032         let body = Client::set_length(msg.head, msg.body);
1033 
1034         let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
1035         dst.reserve(init_cap);
1036 
1037         extend(dst, msg.head.subject.0.as_str().as_bytes());
1038         extend(dst, b" ");
1039         //TODO: add API to http::Uri to encode without std::fmt
1040         let _ = write!(FastWrite(dst), "{} ", msg.head.subject.1);
1041 
1042         match msg.head.version {
1043             Version::HTTP_10 => extend(dst, b"HTTP/1.0"),
1044             Version::HTTP_11 => extend(dst, b"HTTP/1.1"),
1045             Version::HTTP_2 => {
1046                 debug!("request with HTTP2 version coerced to HTTP/1.1");
1047                 extend(dst, b"HTTP/1.1");
1048             }
1049             other => panic!("unexpected request version: {:?}", other),
1050         }
1051         extend(dst, b"\r\n");
1052 
1053         if let Some(orig_headers) = msg.head.extensions.get::<HeaderCaseMap>() {
1054             write_headers_original_case(
1055                 &msg.head.headers,
1056                 orig_headers,
1057                 dst,
1058                 msg.title_case_headers,
1059             );
1060         } else if msg.title_case_headers {
1061             write_headers_title_case(&msg.head.headers, dst);
1062         } else {
1063             write_headers(&msg.head.headers, dst);
1064         }
1065 
1066         extend(dst, b"\r\n");
1067         msg.head.headers.clear(); //TODO: remove when switching to drain()
1068 
1069         Ok(body)
1070     }
1071 
on_error(_err: &crate::Error) -> Option<MessageHead<Self::Outgoing>>1072     fn on_error(_err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
1073         // we can't tell the server about any errors it creates
1074         None
1075     }
1076 
is_client() -> bool1077     fn is_client() -> bool {
1078         true
1079     }
1080 }
1081 
1082 #[cfg(feature = "client")]
1083 impl Client {
1084     /// Returns Some(length, wants_upgrade) if successful.
1085     ///
1086     /// 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>1087     fn decoder(
1088         inc: &MessageHead<StatusCode>,
1089         method: &mut Option<Method>,
1090     ) -> Result<Option<(DecodedLength, bool)>, Parse> {
1091         // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
1092         // 1. HEAD responses, and Status 1xx, 204, and 304 cannot have a body.
1093         // 2. Status 2xx to a CONNECT cannot have a body.
1094         // 3. Transfer-Encoding: chunked has a chunked body.
1095         // 4. If multiple differing Content-Length headers or invalid, close connection.
1096         // 5. Content-Length header has a sized body.
1097         // 6. (irrelevant to Response)
1098         // 7. Read till EOF.
1099 
1100         match inc.subject.as_u16() {
1101             101 => {
1102                 return Ok(Some((DecodedLength::ZERO, true)));
1103             }
1104             100 | 102..=199 => {
1105                 trace!("ignoring informational response: {}", inc.subject.as_u16());
1106                 return Ok(None);
1107             }
1108             204 | 304 => return Ok(Some((DecodedLength::ZERO, false))),
1109             _ => (),
1110         }
1111         match *method {
1112             Some(Method::HEAD) => {
1113                 return Ok(Some((DecodedLength::ZERO, false)));
1114             }
1115             Some(Method::CONNECT) => {
1116                 if let 200..=299 = inc.subject.as_u16() {
1117                     return Ok(Some((DecodedLength::ZERO, true)));
1118                 }
1119             }
1120             Some(_) => {}
1121             None => {
1122                 trace!("Client::decoder is missing the Method");
1123             }
1124         }
1125 
1126         if inc.headers.contains_key(header::TRANSFER_ENCODING) {
1127             // https://tools.ietf.org/html/rfc7230#section-3.3.3
1128             // If Transfer-Encoding header is present, and 'chunked' is
1129             // not the final encoding, and this is a Request, then it is
1130             // malformed. A server should respond with 400 Bad Request.
1131             if inc.version == Version::HTTP_10 {
1132                 debug!("HTTP/1.0 cannot have Transfer-Encoding header");
1133                 Err(Parse::transfer_encoding_unexpected())
1134             } else if headers::transfer_encoding_is_chunked(&inc.headers) {
1135                 Ok(Some((DecodedLength::CHUNKED, false)))
1136             } else {
1137                 trace!("not chunked, read till eof");
1138                 Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1139             }
1140         } else if let Some(len) = headers::content_length_parse_all(&inc.headers) {
1141             Ok(Some((DecodedLength::checked_new(len)?, false)))
1142         } else if inc.headers.contains_key(header::CONTENT_LENGTH) {
1143             debug!("illegal Content-Length header");
1144             Err(Parse::content_length_invalid())
1145         } else {
1146             trace!("neither Transfer-Encoding nor Content-Length");
1147             Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1148         }
1149     }
set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder1150     fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
1151         let body = if let Some(body) = body {
1152             body
1153         } else {
1154             head.headers.remove(header::TRANSFER_ENCODING);
1155             return Encoder::length(0);
1156         };
1157 
1158         // HTTP/1.0 doesn't know about chunked
1159         let can_chunked = head.version == Version::HTTP_11;
1160         let headers = &mut head.headers;
1161 
1162         // If the user already set specific headers, we should respect them, regardless
1163         // of what the HttpBody knows about itself. They set them for a reason.
1164 
1165         // Because of the borrow checker, we can't check the for an existing
1166         // Content-Length header while holding an `Entry` for the Transfer-Encoding
1167         // header, so unfortunately, we must do the check here, first.
1168 
1169         let existing_con_len = headers::content_length_parse_all(headers);
1170         let mut should_remove_con_len = false;
1171 
1172         if !can_chunked {
1173             // Chunked isn't legal, so if it is set, we need to remove it.
1174             if headers.remove(header::TRANSFER_ENCODING).is_some() {
1175                 trace!("removing illegal transfer-encoding header");
1176             }
1177 
1178             return if let Some(len) = existing_con_len {
1179                 Encoder::length(len)
1180             } else if let BodyLength::Known(len) = body {
1181                 set_content_length(headers, len)
1182             } else {
1183                 // HTTP/1.0 client requests without a content-length
1184                 // cannot have any body at all.
1185                 Encoder::length(0)
1186             };
1187         }
1188 
1189         // If the user set a transfer-encoding, respect that. Let's just
1190         // make sure `chunked` is the final encoding.
1191         let encoder = match headers.entry(header::TRANSFER_ENCODING) {
1192             Entry::Occupied(te) => {
1193                 should_remove_con_len = true;
1194                 if headers::is_chunked(te.iter()) {
1195                     Some(Encoder::chunked())
1196                 } else {
1197                     warn!("user provided transfer-encoding does not end in 'chunked'");
1198 
1199                     // There's a Transfer-Encoding, but it doesn't end in 'chunked'!
1200                     // An example that could trigger this:
1201                     //
1202                     //     Transfer-Encoding: gzip
1203                     //
1204                     // This can be bad, depending on if this is a request or a
1205                     // response.
1206                     //
1207                     // - A request is illegal if there is a `Transfer-Encoding`
1208                     //   but it doesn't end in `chunked`.
1209                     // - A response that has `Transfer-Encoding` but doesn't
1210                     //   end in `chunked` isn't illegal, it just forces this
1211                     //   to be close-delimited.
1212                     //
1213                     // We can try to repair this, by adding `chunked` ourselves.
1214 
1215                     headers::add_chunked(te);
1216                     Some(Encoder::chunked())
1217                 }
1218             }
1219             Entry::Vacant(te) => {
1220                 if let Some(len) = existing_con_len {
1221                     Some(Encoder::length(len))
1222                 } else if let BodyLength::Unknown = body {
1223                     // GET, HEAD, and CONNECT almost never have bodies.
1224                     //
1225                     // So instead of sending a "chunked" body with a 0-chunk,
1226                     // assume no body here. If you *must* send a body,
1227                     // set the headers explicitly.
1228                     match head.subject.0 {
1229                         Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)),
1230                         _ => {
1231                             te.insert(HeaderValue::from_static("chunked"));
1232                             Some(Encoder::chunked())
1233                         }
1234                     }
1235                 } else {
1236                     None
1237                 }
1238             }
1239         };
1240 
1241         // This is because we need a second mutable borrow to remove
1242         // content-length header.
1243         if let Some(encoder) = encoder {
1244             if should_remove_con_len && existing_con_len.is_some() {
1245                 headers.remove(header::CONTENT_LENGTH);
1246             }
1247             return encoder;
1248         }
1249 
1250         // User didn't set transfer-encoding, AND we know body length,
1251         // so we can just set the Content-Length automatically.
1252 
1253         let len = if let BodyLength::Known(len) = body {
1254             len
1255         } else {
1256             unreachable!("BodyLength::Unknown would set chunked");
1257         };
1258 
1259         set_content_length(headers, len)
1260     }
1261 }
1262 
set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder1263 fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
1264     // At this point, there should not be a valid Content-Length
1265     // header. However, since we'll be indexing in anyways, we can
1266     // warn the user if there was an existing illegal header.
1267     //
1268     // Or at least, we can in theory. It's actually a little bit slower,
1269     // so perhaps only do that while the user is developing/testing.
1270 
1271     if cfg!(debug_assertions) {
1272         match headers.entry(header::CONTENT_LENGTH) {
1273             Entry::Occupied(mut cl) => {
1274                 // Internal sanity check, we should have already determined
1275                 // that the header was illegal before calling this function.
1276                 debug_assert!(headers::content_length_parse_all_values(cl.iter()).is_none());
1277                 // Uh oh, the user set `Content-Length` headers, but set bad ones.
1278                 // This would be an illegal message anyways, so let's try to repair
1279                 // with our known good length.
1280                 error!("user provided content-length header was invalid");
1281 
1282                 cl.insert(HeaderValue::from(len));
1283                 Encoder::length(len)
1284             }
1285             Entry::Vacant(cl) => {
1286                 cl.insert(HeaderValue::from(len));
1287                 Encoder::length(len)
1288             }
1289         }
1290     } else {
1291         headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
1292         Encoder::length(len)
1293     }
1294 }
1295 
1296 #[derive(Clone, Copy)]
1297 struct HeaderIndices {
1298     name: (usize, usize),
1299     value: (usize, usize),
1300 }
1301 
record_header_indices( bytes: &[u8], headers: &[httparse::Header<'_>], indices: &mut [MaybeUninit<HeaderIndices>], ) -> Result<(), crate::error::Parse>1302 fn record_header_indices(
1303     bytes: &[u8],
1304     headers: &[httparse::Header<'_>],
1305     indices: &mut [MaybeUninit<HeaderIndices>],
1306 ) -> Result<(), crate::error::Parse> {
1307     let bytes_ptr = bytes.as_ptr() as usize;
1308 
1309     for (header, indices) in headers.iter().zip(indices.iter_mut()) {
1310         if header.name.len() >= (1 << 16) {
1311             debug!("header name larger than 64kb: {:?}", header.name);
1312             return Err(crate::error::Parse::TooLarge);
1313         }
1314         let name_start = header.name.as_ptr() as usize - bytes_ptr;
1315         let name_end = name_start + header.name.len();
1316         let value_start = header.value.as_ptr() as usize - bytes_ptr;
1317         let value_end = value_start + header.value.len();
1318 
1319         // FIXME(maybe_uninit_extra)
1320         // FIXME(addr_of)
1321         // Currently we don't have `ptr::addr_of_mut` in stable rust or
1322         // MaybeUninit::write, so this is some way of assigning into a MaybeUninit
1323         // safely
1324         let new_header_indices = HeaderIndices {
1325             name: (name_start, name_end),
1326             value: (value_start, value_end),
1327         };
1328         *indices = MaybeUninit::new(new_header_indices);
1329     }
1330 
1331     Ok(())
1332 }
1333 
1334 // Write header names as title case. The header name is assumed to be ASCII.
title_case(dst: &mut Vec<u8>, name: &[u8])1335 fn title_case(dst: &mut Vec<u8>, name: &[u8]) {
1336     dst.reserve(name.len());
1337 
1338     // Ensure first character is uppercased
1339     let mut prev = b'-';
1340     for &(mut c) in name {
1341         if prev == b'-' {
1342             c.make_ascii_uppercase();
1343         }
1344         dst.push(c);
1345         prev = c;
1346     }
1347 }
1348 
write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>)1349 fn write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>) {
1350     for (name, value) in headers {
1351         title_case(dst, name.as_str().as_bytes());
1352         extend(dst, b": ");
1353         extend(dst, value.as_bytes());
1354         extend(dst, b"\r\n");
1355     }
1356 }
1357 
write_headers(headers: &HeaderMap, dst: &mut Vec<u8>)1358 fn write_headers(headers: &HeaderMap, dst: &mut Vec<u8>) {
1359     for (name, value) in headers {
1360         extend(dst, name.as_str().as_bytes());
1361         extend(dst, b": ");
1362         extend(dst, value.as_bytes());
1363         extend(dst, b"\r\n");
1364     }
1365 }
1366 
1367 #[cold]
write_headers_original_case( headers: &HeaderMap, orig_case: &HeaderCaseMap, dst: &mut Vec<u8>, title_case_headers: bool, )1368 fn write_headers_original_case(
1369     headers: &HeaderMap,
1370     orig_case: &HeaderCaseMap,
1371     dst: &mut Vec<u8>,
1372     title_case_headers: bool,
1373 ) {
1374     // For each header name/value pair, there may be a value in the casemap
1375     // that corresponds to the HeaderValue. So, we iterator all the keys,
1376     // and for each one, try to pair the originally cased name with the value.
1377     //
1378     // TODO: consider adding http::HeaderMap::entries() iterator
1379     for name in headers.keys() {
1380         let mut names = orig_case.get_all(name);
1381 
1382         for value in headers.get_all(name) {
1383             if let Some(orig_name) = names.next() {
1384                 extend(dst, orig_name.as_ref());
1385             } else if title_case_headers {
1386                 title_case(dst, name.as_str().as_bytes());
1387             } else {
1388                 extend(dst, name.as_str().as_bytes());
1389             }
1390 
1391             // Wanted for curl test cases that send `X-Custom-Header:\r\n`
1392             if value.is_empty() {
1393                 extend(dst, b":\r\n");
1394             } else {
1395                 extend(dst, b": ");
1396                 extend(dst, value.as_bytes());
1397                 extend(dst, b"\r\n");
1398             }
1399         }
1400     }
1401 }
1402 
1403 struct FastWrite<'a>(&'a mut Vec<u8>);
1404 
1405 impl<'a> fmt::Write for FastWrite<'a> {
1406     #[inline]
write_str(&mut self, s: &str) -> fmt::Result1407     fn write_str(&mut self, s: &str) -> fmt::Result {
1408         extend(self.0, s.as_bytes());
1409         Ok(())
1410     }
1411 
1412     #[inline]
write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result1413     fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
1414         fmt::write(self, args)
1415     }
1416 }
1417 
1418 #[inline]
extend(dst: &mut Vec<u8>, data: &[u8])1419 fn extend(dst: &mut Vec<u8>, data: &[u8]) {
1420     dst.extend_from_slice(data);
1421 }
1422 
1423 #[cfg(test)]
1424 mod tests {
1425     use bytes::BytesMut;
1426 
1427     use super::*;
1428 
1429     #[test]
test_parse_request()1430     fn test_parse_request() {
1431         let _ = pretty_env_logger::try_init();
1432         let mut raw = BytesMut::from("GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1433         let mut method = None;
1434         let msg = Server::parse(
1435             &mut raw,
1436             ParseContext {
1437                 cached_headers: &mut None,
1438                 req_method: &mut method,
1439                 h1_parser_config: Default::default(),
1440                 preserve_header_case: false,
1441                 h09_responses: false,
1442                 #[cfg(feature = "ffi")]
1443                 on_informational: &mut None,
1444                 #[cfg(feature = "ffi")]
1445                 raw_headers: false,
1446             },
1447         )
1448         .unwrap()
1449         .unwrap();
1450         assert_eq!(raw.len(), 0);
1451         assert_eq!(msg.head.subject.0, crate::Method::GET);
1452         assert_eq!(msg.head.subject.1, "/echo");
1453         assert_eq!(msg.head.version, crate::Version::HTTP_11);
1454         assert_eq!(msg.head.headers.len(), 1);
1455         assert_eq!(msg.head.headers["Host"], "hyper.rs");
1456         assert_eq!(method, Some(crate::Method::GET));
1457     }
1458 
1459     #[test]
test_parse_response()1460     fn test_parse_response() {
1461         let _ = pretty_env_logger::try_init();
1462         let mut raw = BytesMut::from("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1463         let ctx = ParseContext {
1464             cached_headers: &mut None,
1465             req_method: &mut Some(crate::Method::GET),
1466             h1_parser_config: Default::default(),
1467             preserve_header_case: false,
1468             h09_responses: false,
1469             #[cfg(feature = "ffi")]
1470             on_informational: &mut None,
1471             #[cfg(feature = "ffi")]
1472             raw_headers: false,
1473         };
1474         let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1475         assert_eq!(raw.len(), 0);
1476         assert_eq!(msg.head.subject, crate::StatusCode::OK);
1477         assert_eq!(msg.head.version, crate::Version::HTTP_11);
1478         assert_eq!(msg.head.headers.len(), 1);
1479         assert_eq!(msg.head.headers["Content-Length"], "0");
1480     }
1481 
1482     #[test]
test_parse_request_errors()1483     fn test_parse_request_errors() {
1484         let mut raw = BytesMut::from("GET htt:p// HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1485         let ctx = ParseContext {
1486             cached_headers: &mut None,
1487             req_method: &mut None,
1488             h1_parser_config: Default::default(),
1489             preserve_header_case: false,
1490             h09_responses: false,
1491             #[cfg(feature = "ffi")]
1492             on_informational: &mut None,
1493             #[cfg(feature = "ffi")]
1494             raw_headers: false,
1495         };
1496         Server::parse(&mut raw, ctx).unwrap_err();
1497     }
1498 
1499     const H09_RESPONSE: &'static str = "Baguettes are super delicious, don't you agree?";
1500 
1501     #[test]
test_parse_response_h09_allowed()1502     fn test_parse_response_h09_allowed() {
1503         let _ = pretty_env_logger::try_init();
1504         let mut raw = BytesMut::from(H09_RESPONSE);
1505         let ctx = ParseContext {
1506             cached_headers: &mut None,
1507             req_method: &mut Some(crate::Method::GET),
1508             h1_parser_config: Default::default(),
1509             preserve_header_case: false,
1510             h09_responses: true,
1511             #[cfg(feature = "ffi")]
1512             on_informational: &mut None,
1513             #[cfg(feature = "ffi")]
1514             raw_headers: false,
1515         };
1516         let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1517         assert_eq!(raw, H09_RESPONSE);
1518         assert_eq!(msg.head.subject, crate::StatusCode::OK);
1519         assert_eq!(msg.head.version, crate::Version::HTTP_09);
1520         assert_eq!(msg.head.headers.len(), 0);
1521     }
1522 
1523     #[test]
test_parse_response_h09_rejected()1524     fn test_parse_response_h09_rejected() {
1525         let _ = pretty_env_logger::try_init();
1526         let mut raw = BytesMut::from(H09_RESPONSE);
1527         let ctx = ParseContext {
1528             cached_headers: &mut None,
1529             req_method: &mut Some(crate::Method::GET),
1530             h1_parser_config: Default::default(),
1531             preserve_header_case: false,
1532             h09_responses: false,
1533             #[cfg(feature = "ffi")]
1534             on_informational: &mut None,
1535             #[cfg(feature = "ffi")]
1536             raw_headers: false,
1537         };
1538         Client::parse(&mut raw, ctx).unwrap_err();
1539         assert_eq!(raw, H09_RESPONSE);
1540     }
1541 
1542     const RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &'static str =
1543         "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\n\r\n";
1544 
1545     #[test]
test_parse_allow_response_with_spaces_before_colons()1546     fn test_parse_allow_response_with_spaces_before_colons() {
1547         use httparse::ParserConfig;
1548 
1549         let _ = pretty_env_logger::try_init();
1550         let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1551         let mut h1_parser_config = ParserConfig::default();
1552         h1_parser_config.allow_spaces_after_header_name_in_responses(true);
1553         let ctx = ParseContext {
1554             cached_headers: &mut None,
1555             req_method: &mut Some(crate::Method::GET),
1556             h1_parser_config,
1557             preserve_header_case: false,
1558             h09_responses: false,
1559             #[cfg(feature = "ffi")]
1560             on_informational: &mut None,
1561             #[cfg(feature = "ffi")]
1562             raw_headers: false,
1563         };
1564         let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1565         assert_eq!(raw.len(), 0);
1566         assert_eq!(msg.head.subject, crate::StatusCode::OK);
1567         assert_eq!(msg.head.version, crate::Version::HTTP_11);
1568         assert_eq!(msg.head.headers.len(), 1);
1569         assert_eq!(msg.head.headers["Access-Control-Allow-Credentials"], "true");
1570     }
1571 
1572     #[test]
test_parse_reject_response_with_spaces_before_colons()1573     fn test_parse_reject_response_with_spaces_before_colons() {
1574         let _ = pretty_env_logger::try_init();
1575         let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1576         let ctx = ParseContext {
1577             cached_headers: &mut None,
1578             req_method: &mut Some(crate::Method::GET),
1579             h1_parser_config: Default::default(),
1580             preserve_header_case: false,
1581             h09_responses: false,
1582             #[cfg(feature = "ffi")]
1583             on_informational: &mut None,
1584             #[cfg(feature = "ffi")]
1585             raw_headers: false,
1586         };
1587         Client::parse(&mut raw, ctx).unwrap_err();
1588     }
1589 
1590     #[test]
test_parse_preserve_header_case_in_request()1591     fn test_parse_preserve_header_case_in_request() {
1592         let mut raw =
1593             BytesMut::from("GET / HTTP/1.1\r\nHost: hyper.rs\r\nX-BREAD: baguette\r\n\r\n");
1594         let ctx = ParseContext {
1595             cached_headers: &mut None,
1596             req_method: &mut None,
1597             h1_parser_config: Default::default(),
1598             preserve_header_case: true,
1599             h09_responses: false,
1600             #[cfg(feature = "ffi")]
1601             on_informational: &mut None,
1602             #[cfg(feature = "ffi")]
1603             raw_headers: false,
1604         };
1605         let parsed_message = Server::parse(&mut raw, ctx).unwrap().unwrap();
1606         let orig_headers = parsed_message
1607             .head
1608             .extensions
1609             .get::<HeaderCaseMap>()
1610             .unwrap();
1611         assert_eq!(
1612             orig_headers
1613                 .get_all_internal(&HeaderName::from_static("host"))
1614                 .into_iter()
1615                 .collect::<Vec<_>>(),
1616             vec![&Bytes::from("Host")]
1617         );
1618         assert_eq!(
1619             orig_headers
1620                 .get_all_internal(&HeaderName::from_static("x-bread"))
1621                 .into_iter()
1622                 .collect::<Vec<_>>(),
1623             vec![&Bytes::from("X-BREAD")]
1624         );
1625     }
1626 
1627     #[test]
test_decoder_request()1628     fn test_decoder_request() {
1629         fn parse(s: &str) -> ParsedMessage<RequestLine> {
1630             let mut bytes = BytesMut::from(s);
1631             Server::parse(
1632                 &mut bytes,
1633                 ParseContext {
1634                     cached_headers: &mut None,
1635                     req_method: &mut None,
1636                     h1_parser_config: Default::default(),
1637                     preserve_header_case: false,
1638                     h09_responses: false,
1639                     #[cfg(feature = "ffi")]
1640                     on_informational: &mut None,
1641                     #[cfg(feature = "ffi")]
1642                     raw_headers: false,
1643                 },
1644             )
1645             .expect("parse ok")
1646             .expect("parse complete")
1647         }
1648 
1649         fn parse_err(s: &str, comment: &str) -> crate::error::Parse {
1650             let mut bytes = BytesMut::from(s);
1651             Server::parse(
1652                 &mut bytes,
1653                 ParseContext {
1654                     cached_headers: &mut None,
1655                     req_method: &mut None,
1656                     h1_parser_config: Default::default(),
1657                     preserve_header_case: false,
1658                     h09_responses: false,
1659                     #[cfg(feature = "ffi")]
1660                     on_informational: &mut None,
1661                     #[cfg(feature = "ffi")]
1662                     raw_headers: false,
1663                 },
1664             )
1665             .expect_err(comment)
1666         }
1667 
1668         // no length or transfer-encoding means 0-length body
1669         assert_eq!(
1670             parse(
1671                 "\
1672                  GET / HTTP/1.1\r\n\
1673                  \r\n\
1674                  "
1675             )
1676             .decode,
1677             DecodedLength::ZERO
1678         );
1679 
1680         assert_eq!(
1681             parse(
1682                 "\
1683                  POST / HTTP/1.1\r\n\
1684                  \r\n\
1685                  "
1686             )
1687             .decode,
1688             DecodedLength::ZERO
1689         );
1690 
1691         // transfer-encoding: chunked
1692         assert_eq!(
1693             parse(
1694                 "\
1695                  POST / HTTP/1.1\r\n\
1696                  transfer-encoding: chunked\r\n\
1697                  \r\n\
1698                  "
1699             )
1700             .decode,
1701             DecodedLength::CHUNKED
1702         );
1703 
1704         assert_eq!(
1705             parse(
1706                 "\
1707                  POST / HTTP/1.1\r\n\
1708                  transfer-encoding: gzip, chunked\r\n\
1709                  \r\n\
1710                  "
1711             )
1712             .decode,
1713             DecodedLength::CHUNKED
1714         );
1715 
1716         assert_eq!(
1717             parse(
1718                 "\
1719                  POST / HTTP/1.1\r\n\
1720                  transfer-encoding: gzip\r\n\
1721                  transfer-encoding: chunked\r\n\
1722                  \r\n\
1723                  "
1724             )
1725             .decode,
1726             DecodedLength::CHUNKED
1727         );
1728 
1729         // content-length
1730         assert_eq!(
1731             parse(
1732                 "\
1733                  POST / HTTP/1.1\r\n\
1734                  content-length: 10\r\n\
1735                  \r\n\
1736                  "
1737             )
1738             .decode,
1739             DecodedLength::new(10)
1740         );
1741 
1742         // transfer-encoding and content-length = chunked
1743         assert_eq!(
1744             parse(
1745                 "\
1746                  POST / HTTP/1.1\r\n\
1747                  content-length: 10\r\n\
1748                  transfer-encoding: chunked\r\n\
1749                  \r\n\
1750                  "
1751             )
1752             .decode,
1753             DecodedLength::CHUNKED
1754         );
1755 
1756         assert_eq!(
1757             parse(
1758                 "\
1759                  POST / HTTP/1.1\r\n\
1760                  transfer-encoding: chunked\r\n\
1761                  content-length: 10\r\n\
1762                  \r\n\
1763                  "
1764             )
1765             .decode,
1766             DecodedLength::CHUNKED
1767         );
1768 
1769         assert_eq!(
1770             parse(
1771                 "\
1772                  POST / HTTP/1.1\r\n\
1773                  transfer-encoding: gzip\r\n\
1774                  content-length: 10\r\n\
1775                  transfer-encoding: chunked\r\n\
1776                  \r\n\
1777                  "
1778             )
1779             .decode,
1780             DecodedLength::CHUNKED
1781         );
1782 
1783         // multiple content-lengths of same value are fine
1784         assert_eq!(
1785             parse(
1786                 "\
1787                  POST / HTTP/1.1\r\n\
1788                  content-length: 10\r\n\
1789                  content-length: 10\r\n\
1790                  \r\n\
1791                  "
1792             )
1793             .decode,
1794             DecodedLength::new(10)
1795         );
1796 
1797         // multiple content-lengths with different values is an error
1798         parse_err(
1799             "\
1800              POST / HTTP/1.1\r\n\
1801              content-length: 10\r\n\
1802              content-length: 11\r\n\
1803              \r\n\
1804              ",
1805             "multiple content-lengths",
1806         );
1807 
1808         // content-length with prefix is not allowed
1809         parse_err(
1810             "\
1811              POST / HTTP/1.1\r\n\
1812              content-length: +10\r\n\
1813              \r\n\
1814              ",
1815             "prefixed content-length",
1816         );
1817 
1818         // transfer-encoding that isn't chunked is an error
1819         parse_err(
1820             "\
1821              POST / HTTP/1.1\r\n\
1822              transfer-encoding: gzip\r\n\
1823              \r\n\
1824              ",
1825             "transfer-encoding but not chunked",
1826         );
1827 
1828         parse_err(
1829             "\
1830              POST / HTTP/1.1\r\n\
1831              transfer-encoding: chunked, gzip\r\n\
1832              \r\n\
1833              ",
1834             "transfer-encoding doesn't end in chunked",
1835         );
1836 
1837         parse_err(
1838             "\
1839              POST / HTTP/1.1\r\n\
1840              transfer-encoding: chunked\r\n\
1841              transfer-encoding: afterlol\r\n\
1842              \r\n\
1843              ",
1844             "transfer-encoding multiple lines doesn't end in chunked",
1845         );
1846 
1847         // http/1.0
1848 
1849         assert_eq!(
1850             parse(
1851                 "\
1852                  POST / HTTP/1.0\r\n\
1853                  content-length: 10\r\n\
1854                  \r\n\
1855                  "
1856             )
1857             .decode,
1858             DecodedLength::new(10)
1859         );
1860 
1861         // 1.0 doesn't understand chunked, so its an error
1862         parse_err(
1863             "\
1864              POST / HTTP/1.0\r\n\
1865              transfer-encoding: chunked\r\n\
1866              \r\n\
1867              ",
1868             "1.0 chunked",
1869         );
1870     }
1871 
1872     #[test]
test_decoder_response()1873     fn test_decoder_response() {
1874         fn parse(s: &str) -> ParsedMessage<StatusCode> {
1875             parse_with_method(s, Method::GET)
1876         }
1877 
1878         fn parse_ignores(s: &str) {
1879             let mut bytes = BytesMut::from(s);
1880             assert!(Client::parse(
1881                 &mut bytes,
1882                 ParseContext {
1883                     cached_headers: &mut None,
1884                     req_method: &mut Some(Method::GET),
1885                     h1_parser_config: Default::default(),
1886                     preserve_header_case: false,
1887                     h09_responses: false,
1888                     #[cfg(feature = "ffi")]
1889                     on_informational: &mut None,
1890                     #[cfg(feature = "ffi")]
1891                     raw_headers: false,
1892                 }
1893             )
1894             .expect("parse ok")
1895             .is_none())
1896         }
1897 
1898         fn parse_with_method(s: &str, m: Method) -> ParsedMessage<StatusCode> {
1899             let mut bytes = BytesMut::from(s);
1900             Client::parse(
1901                 &mut bytes,
1902                 ParseContext {
1903                     cached_headers: &mut None,
1904                     req_method: &mut Some(m),
1905                     h1_parser_config: Default::default(),
1906                     preserve_header_case: false,
1907                     h09_responses: false,
1908                     #[cfg(feature = "ffi")]
1909                     on_informational: &mut None,
1910                     #[cfg(feature = "ffi")]
1911                     raw_headers: false,
1912                 },
1913             )
1914             .expect("parse ok")
1915             .expect("parse complete")
1916         }
1917 
1918         fn parse_err(s: &str) -> crate::error::Parse {
1919             let mut bytes = BytesMut::from(s);
1920             Client::parse(
1921                 &mut bytes,
1922                 ParseContext {
1923                     cached_headers: &mut None,
1924                     req_method: &mut Some(Method::GET),
1925                     h1_parser_config: Default::default(),
1926                     preserve_header_case: false,
1927                     h09_responses: false,
1928                     #[cfg(feature = "ffi")]
1929                     on_informational: &mut None,
1930                     #[cfg(feature = "ffi")]
1931                     raw_headers: false,
1932                 },
1933             )
1934             .expect_err("parse should err")
1935         }
1936 
1937         // no content-length or transfer-encoding means close-delimited
1938         assert_eq!(
1939             parse(
1940                 "\
1941                  HTTP/1.1 200 OK\r\n\
1942                  \r\n\
1943                  "
1944             )
1945             .decode,
1946             DecodedLength::CLOSE_DELIMITED
1947         );
1948 
1949         // 204 and 304 never have a body
1950         assert_eq!(
1951             parse(
1952                 "\
1953                  HTTP/1.1 204 No Content\r\n\
1954                  \r\n\
1955                  "
1956             )
1957             .decode,
1958             DecodedLength::ZERO
1959         );
1960 
1961         assert_eq!(
1962             parse(
1963                 "\
1964                  HTTP/1.1 304 Not Modified\r\n\
1965                  \r\n\
1966                  "
1967             )
1968             .decode,
1969             DecodedLength::ZERO
1970         );
1971 
1972         // content-length
1973         assert_eq!(
1974             parse(
1975                 "\
1976                  HTTP/1.1 200 OK\r\n\
1977                  content-length: 8\r\n\
1978                  \r\n\
1979                  "
1980             )
1981             .decode,
1982             DecodedLength::new(8)
1983         );
1984 
1985         assert_eq!(
1986             parse(
1987                 "\
1988                  HTTP/1.1 200 OK\r\n\
1989                  content-length: 8\r\n\
1990                  content-length: 8\r\n\
1991                  \r\n\
1992                  "
1993             )
1994             .decode,
1995             DecodedLength::new(8)
1996         );
1997 
1998         parse_err(
1999             "\
2000              HTTP/1.1 200 OK\r\n\
2001              content-length: 8\r\n\
2002              content-length: 9\r\n\
2003              \r\n\
2004              ",
2005         );
2006 
2007         parse_err(
2008             "\
2009              HTTP/1.1 200 OK\r\n\
2010              content-length: +8\r\n\
2011              \r\n\
2012              ",
2013         );
2014 
2015         // transfer-encoding: chunked
2016         assert_eq!(
2017             parse(
2018                 "\
2019                  HTTP/1.1 200 OK\r\n\
2020                  transfer-encoding: chunked\r\n\
2021                  \r\n\
2022                  "
2023             )
2024             .decode,
2025             DecodedLength::CHUNKED
2026         );
2027 
2028         // transfer-encoding not-chunked is close-delimited
2029         assert_eq!(
2030             parse(
2031                 "\
2032                  HTTP/1.1 200 OK\r\n\
2033                  transfer-encoding: yolo\r\n\
2034                  \r\n\
2035                  "
2036             )
2037             .decode,
2038             DecodedLength::CLOSE_DELIMITED
2039         );
2040 
2041         // transfer-encoding and content-length = chunked
2042         assert_eq!(
2043             parse(
2044                 "\
2045                  HTTP/1.1 200 OK\r\n\
2046                  content-length: 10\r\n\
2047                  transfer-encoding: chunked\r\n\
2048                  \r\n\
2049                  "
2050             )
2051             .decode,
2052             DecodedLength::CHUNKED
2053         );
2054 
2055         // HEAD can have content-length, but not body
2056         assert_eq!(
2057             parse_with_method(
2058                 "\
2059                  HTTP/1.1 200 OK\r\n\
2060                  content-length: 8\r\n\
2061                  \r\n\
2062                  ",
2063                 Method::HEAD
2064             )
2065             .decode,
2066             DecodedLength::ZERO
2067         );
2068 
2069         // CONNECT with 200 never has body
2070         {
2071             let msg = parse_with_method(
2072                 "\
2073                  HTTP/1.1 200 OK\r\n\
2074                  \r\n\
2075                  ",
2076                 Method::CONNECT,
2077             );
2078             assert_eq!(msg.decode, DecodedLength::ZERO);
2079             assert!(!msg.keep_alive, "should be upgrade");
2080             assert!(msg.wants_upgrade, "should be upgrade");
2081         }
2082 
2083         // CONNECT receiving non 200 can have a body
2084         assert_eq!(
2085             parse_with_method(
2086                 "\
2087                  HTTP/1.1 400 Bad Request\r\n\
2088                  \r\n\
2089                  ",
2090                 Method::CONNECT
2091             )
2092             .decode,
2093             DecodedLength::CLOSE_DELIMITED
2094         );
2095 
2096         // 1xx status codes
2097         parse_ignores(
2098             "\
2099              HTTP/1.1 100 Continue\r\n\
2100              \r\n\
2101              ",
2102         );
2103 
2104         parse_ignores(
2105             "\
2106              HTTP/1.1 103 Early Hints\r\n\
2107              \r\n\
2108              ",
2109         );
2110 
2111         // 101 upgrade not supported yet
2112         {
2113             let msg = parse(
2114                 "\
2115                  HTTP/1.1 101 Switching Protocols\r\n\
2116                  \r\n\
2117                  ",
2118             );
2119             assert_eq!(msg.decode, DecodedLength::ZERO);
2120             assert!(!msg.keep_alive, "should be last");
2121             assert!(msg.wants_upgrade, "should be upgrade");
2122         }
2123 
2124         // http/1.0
2125         assert_eq!(
2126             parse(
2127                 "\
2128                  HTTP/1.0 200 OK\r\n\
2129                  \r\n\
2130                  "
2131             )
2132             .decode,
2133             DecodedLength::CLOSE_DELIMITED
2134         );
2135 
2136         // 1.0 doesn't understand chunked
2137         parse_err(
2138             "\
2139              HTTP/1.0 200 OK\r\n\
2140              transfer-encoding: chunked\r\n\
2141              \r\n\
2142              ",
2143         );
2144 
2145         // keep-alive
2146         assert!(
2147             parse(
2148                 "\
2149                  HTTP/1.1 200 OK\r\n\
2150                  content-length: 0\r\n\
2151                  \r\n\
2152                  "
2153             )
2154             .keep_alive,
2155             "HTTP/1.1 keep-alive is default"
2156         );
2157 
2158         assert!(
2159             !parse(
2160                 "\
2161                  HTTP/1.1 200 OK\r\n\
2162                  content-length: 0\r\n\
2163                  connection: foo, close, bar\r\n\
2164                  \r\n\
2165                  "
2166             )
2167             .keep_alive,
2168             "connection close is always close"
2169         );
2170 
2171         assert!(
2172             !parse(
2173                 "\
2174                  HTTP/1.0 200 OK\r\n\
2175                  content-length: 0\r\n\
2176                  \r\n\
2177                  "
2178             )
2179             .keep_alive,
2180             "HTTP/1.0 close is default"
2181         );
2182 
2183         assert!(
2184             parse(
2185                 "\
2186                  HTTP/1.0 200 OK\r\n\
2187                  content-length: 0\r\n\
2188                  connection: foo, keep-alive, bar\r\n\
2189                  \r\n\
2190                  "
2191             )
2192             .keep_alive,
2193             "connection keep-alive is always keep-alive"
2194         );
2195     }
2196 
2197     #[test]
test_client_request_encode_title_case()2198     fn test_client_request_encode_title_case() {
2199         use crate::proto::BodyLength;
2200         use http::header::HeaderValue;
2201 
2202         let mut head = MessageHead::default();
2203         head.headers
2204             .insert("content-length", HeaderValue::from_static("10"));
2205         head.headers
2206             .insert("content-type", HeaderValue::from_static("application/json"));
2207         head.headers.insert("*-*", HeaderValue::from_static("o_o"));
2208 
2209         let mut vec = Vec::new();
2210         Client::encode(
2211             Encode {
2212                 head: &mut head,
2213                 body: Some(BodyLength::Known(10)),
2214                 keep_alive: true,
2215                 req_method: &mut None,
2216                 title_case_headers: true,
2217             },
2218             &mut vec,
2219         )
2220         .unwrap();
2221 
2222         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());
2223     }
2224 
2225     #[test]
test_client_request_encode_orig_case()2226     fn test_client_request_encode_orig_case() {
2227         use crate::proto::BodyLength;
2228         use http::header::{HeaderValue, CONTENT_LENGTH};
2229 
2230         let mut head = MessageHead::default();
2231         head.headers
2232             .insert("content-length", HeaderValue::from_static("10"));
2233         head.headers
2234             .insert("content-type", HeaderValue::from_static("application/json"));
2235 
2236         let mut orig_headers = HeaderCaseMap::default();
2237         orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2238         head.extensions.insert(orig_headers);
2239 
2240         let mut vec = Vec::new();
2241         Client::encode(
2242             Encode {
2243                 head: &mut head,
2244                 body: Some(BodyLength::Known(10)),
2245                 keep_alive: true,
2246                 req_method: &mut None,
2247                 title_case_headers: false,
2248             },
2249             &mut vec,
2250         )
2251         .unwrap();
2252 
2253         assert_eq!(
2254             &*vec,
2255             b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\n\r\n"
2256                 .as_ref(),
2257         );
2258     }
2259     #[test]
test_client_request_encode_orig_and_title_case()2260     fn test_client_request_encode_orig_and_title_case() {
2261         use crate::proto::BodyLength;
2262         use http::header::{HeaderValue, CONTENT_LENGTH};
2263 
2264         let mut head = MessageHead::default();
2265         head.headers
2266             .insert("content-length", HeaderValue::from_static("10"));
2267         head.headers
2268             .insert("content-type", HeaderValue::from_static("application/json"));
2269 
2270         let mut orig_headers = HeaderCaseMap::default();
2271         orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2272         head.extensions.insert(orig_headers);
2273 
2274         let mut vec = Vec::new();
2275         Client::encode(
2276             Encode {
2277                 head: &mut head,
2278                 body: Some(BodyLength::Known(10)),
2279                 keep_alive: true,
2280                 req_method: &mut None,
2281                 title_case_headers: true,
2282             },
2283             &mut vec,
2284         )
2285         .unwrap();
2286 
2287         assert_eq!(
2288             &*vec,
2289             b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\n\r\n"
2290                 .as_ref(),
2291         );
2292     }
2293 
2294     #[test]
test_server_encode_connect_method()2295     fn test_server_encode_connect_method() {
2296         let mut head = MessageHead::default();
2297 
2298         let mut vec = Vec::new();
2299         let encoder = Server::encode(
2300             Encode {
2301                 head: &mut head,
2302                 body: None,
2303                 keep_alive: true,
2304                 req_method: &mut Some(Method::CONNECT),
2305                 title_case_headers: false,
2306             },
2307             &mut vec,
2308         )
2309         .unwrap();
2310 
2311         assert!(encoder.is_last());
2312     }
2313 
2314     #[test]
test_server_response_encode_title_case()2315     fn test_server_response_encode_title_case() {
2316         use crate::proto::BodyLength;
2317         use http::header::HeaderValue;
2318 
2319         let mut head = MessageHead::default();
2320         head.headers
2321             .insert("content-length", HeaderValue::from_static("10"));
2322         head.headers
2323             .insert("content-type", HeaderValue::from_static("application/json"));
2324         head.headers
2325             .insert("weird--header", HeaderValue::from_static(""));
2326 
2327         let mut vec = Vec::new();
2328         Server::encode(
2329             Encode {
2330                 head: &mut head,
2331                 body: Some(BodyLength::Known(10)),
2332                 keep_alive: true,
2333                 req_method: &mut None,
2334                 title_case_headers: true,
2335             },
2336             &mut vec,
2337         )
2338         .unwrap();
2339 
2340         let expected_response =
2341             b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: application/json\r\nWeird--Header: \r\n";
2342 
2343         assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2344     }
2345 
2346     #[test]
test_server_response_encode_orig_case()2347     fn test_server_response_encode_orig_case() {
2348         use crate::proto::BodyLength;
2349         use http::header::{HeaderValue, CONTENT_LENGTH};
2350 
2351         let mut head = MessageHead::default();
2352         head.headers
2353             .insert("content-length", HeaderValue::from_static("10"));
2354         head.headers
2355             .insert("content-type", HeaderValue::from_static("application/json"));
2356 
2357         let mut orig_headers = HeaderCaseMap::default();
2358         orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2359         head.extensions.insert(orig_headers);
2360 
2361         let mut vec = Vec::new();
2362         Server::encode(
2363             Encode {
2364                 head: &mut head,
2365                 body: Some(BodyLength::Known(10)),
2366                 keep_alive: true,
2367                 req_method: &mut None,
2368                 title_case_headers: false,
2369             },
2370             &mut vec,
2371         )
2372         .unwrap();
2373 
2374         let expected_response =
2375             b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\ndate: ";
2376 
2377         assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2378     }
2379 
2380     #[test]
test_server_response_encode_orig_and_title_case()2381     fn test_server_response_encode_orig_and_title_case() {
2382         use crate::proto::BodyLength;
2383         use http::header::{HeaderValue, CONTENT_LENGTH};
2384 
2385         let mut head = MessageHead::default();
2386         head.headers
2387             .insert("content-length", HeaderValue::from_static("10"));
2388         head.headers
2389             .insert("content-type", HeaderValue::from_static("application/json"));
2390 
2391         let mut orig_headers = HeaderCaseMap::default();
2392         orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2393         head.extensions.insert(orig_headers);
2394 
2395         let mut vec = Vec::new();
2396         Server::encode(
2397             Encode {
2398                 head: &mut head,
2399                 body: Some(BodyLength::Known(10)),
2400                 keep_alive: true,
2401                 req_method: &mut None,
2402                 title_case_headers: true,
2403             },
2404             &mut vec,
2405         )
2406         .unwrap();
2407 
2408         let expected_response =
2409             b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\nDate: ";
2410 
2411         assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
2412     }
2413 
2414     #[test]
parse_header_htabs()2415     fn parse_header_htabs() {
2416         let mut bytes = BytesMut::from("HTTP/1.1 200 OK\r\nserver: hello\tworld\r\n\r\n");
2417         let parsed = Client::parse(
2418             &mut bytes,
2419             ParseContext {
2420                 cached_headers: &mut None,
2421                 req_method: &mut Some(Method::GET),
2422                 h1_parser_config: Default::default(),
2423                 preserve_header_case: false,
2424                 h09_responses: false,
2425                 #[cfg(feature = "ffi")]
2426                 on_informational: &mut None,
2427                 #[cfg(feature = "ffi")]
2428                 raw_headers: false,
2429             },
2430         )
2431         .expect("parse ok")
2432         .expect("parse complete");
2433 
2434         assert_eq!(parsed.head.headers["server"], "hello\tworld");
2435     }
2436 
2437     #[test]
test_write_headers_orig_case_empty_value()2438     fn test_write_headers_orig_case_empty_value() {
2439         let mut headers = HeaderMap::new();
2440         let name = http::header::HeaderName::from_static("x-empty");
2441         headers.insert(&name, "".parse().expect("parse empty"));
2442         let mut orig_cases = HeaderCaseMap::default();
2443         orig_cases.insert(name, Bytes::from_static(b"X-EmptY"));
2444 
2445         let mut dst = Vec::new();
2446         super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
2447 
2448         assert_eq!(
2449             dst, b"X-EmptY:\r\n",
2450             "there should be no space between the colon and CRLF"
2451         );
2452     }
2453 
2454     #[test]
test_write_headers_orig_case_multiple_entries()2455     fn test_write_headers_orig_case_multiple_entries() {
2456         let mut headers = HeaderMap::new();
2457         let name = http::header::HeaderName::from_static("x-empty");
2458         headers.insert(&name, "a".parse().unwrap());
2459         headers.append(&name, "b".parse().unwrap());
2460 
2461         let mut orig_cases = HeaderCaseMap::default();
2462         orig_cases.insert(name.clone(), Bytes::from_static(b"X-Empty"));
2463         orig_cases.append(name, Bytes::from_static(b"X-EMPTY"));
2464 
2465         let mut dst = Vec::new();
2466         super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
2467 
2468         assert_eq!(dst, b"X-Empty: a\r\nX-EMPTY: b\r\n");
2469     }
2470 
2471     #[cfg(feature = "nightly")]
2472     use test::Bencher;
2473 
2474     #[cfg(feature = "nightly")]
2475     #[bench]
bench_parse_incoming(b: &mut Bencher)2476     fn bench_parse_incoming(b: &mut Bencher) {
2477         let mut raw = BytesMut::from(
2478             &b"GET /super_long_uri/and_whatever?what_should_we_talk_about/\
2479             I_wonder/Hard_to_write_in_an_uri_after_all/you_have_to_make\
2480             _up_the_punctuation_yourself/how_fun_is_that?test=foo&test1=\
2481             foo1&test2=foo2&test3=foo3&test4=foo4 HTTP/1.1\r\nHost: \
2482             hyper.rs\r\nAccept: a lot of things\r\nAccept-Charset: \
2483             utf8\r\nAccept-Encoding: *\r\nAccess-Control-Allow-\
2484             Credentials: None\r\nAccess-Control-Allow-Origin: None\r\n\
2485             Access-Control-Allow-Methods: None\r\nAccess-Control-Allow-\
2486             Headers: None\r\nContent-Encoding: utf8\r\nContent-Security-\
2487             Policy: None\r\nContent-Type: text/html\r\nOrigin: hyper\
2488             \r\nSec-Websocket-Extensions: It looks super important!\r\n\
2489             Sec-Websocket-Origin: hyper\r\nSec-Websocket-Version: 4.3\r\
2490             \nStrict-Transport-Security: None\r\nUser-Agent: hyper\r\n\
2491             X-Content-Duration: None\r\nX-Content-Security-Policy: None\
2492             \r\nX-DNSPrefetch-Control: None\r\nX-Frame-Options: \
2493             Something important obviously\r\nX-Requested-With: Nothing\
2494             \r\n\r\n"[..],
2495         );
2496         let len = raw.len();
2497         let mut headers = Some(HeaderMap::new());
2498 
2499         b.bytes = len as u64;
2500         b.iter(|| {
2501             let mut msg = Server::parse(
2502                 &mut raw,
2503                 ParseContext {
2504                     cached_headers: &mut headers,
2505                     req_method: &mut None,
2506                     h1_parser_config: Default::default(),
2507                     preserve_header_case: false,
2508                     h09_responses: false,
2509                     #[cfg(feature = "ffi")]
2510                     on_informational: &mut None,
2511                     #[cfg(feature = "ffi")]
2512                     raw_headers: false,
2513                 },
2514             )
2515             .unwrap()
2516             .unwrap();
2517             ::test::black_box(&msg);
2518             msg.head.headers.clear();
2519             headers = Some(msg.head.headers);
2520             restart(&mut raw, len);
2521         });
2522 
2523         fn restart(b: &mut BytesMut, len: usize) {
2524             b.reserve(1);
2525             unsafe {
2526                 b.set_len(len);
2527             }
2528         }
2529     }
2530 
2531     #[cfg(feature = "nightly")]
2532     #[bench]
bench_parse_short(b: &mut Bencher)2533     fn bench_parse_short(b: &mut Bencher) {
2534         let s = &b"GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"[..];
2535         let mut raw = BytesMut::from(s);
2536         let len = raw.len();
2537         let mut headers = Some(HeaderMap::new());
2538 
2539         b.bytes = len as u64;
2540         b.iter(|| {
2541             let mut msg = Server::parse(
2542                 &mut raw,
2543                 ParseContext {
2544                     cached_headers: &mut headers,
2545                     req_method: &mut None,
2546                     h1_parser_config: Default::default(),
2547                     preserve_header_case: false,
2548                     h09_responses: false,
2549                     #[cfg(feature = "ffi")]
2550                     on_informational: &mut None,
2551                     #[cfg(feature = "ffi")]
2552                     raw_headers: false,
2553                 },
2554             )
2555             .unwrap()
2556             .unwrap();
2557             ::test::black_box(&msg);
2558             msg.head.headers.clear();
2559             headers = Some(msg.head.headers);
2560             restart(&mut raw, len);
2561         });
2562 
2563         fn restart(b: &mut BytesMut, len: usize) {
2564             b.reserve(1);
2565             unsafe {
2566                 b.set_len(len);
2567             }
2568         }
2569     }
2570 
2571     #[cfg(feature = "nightly")]
2572     #[bench]
bench_server_encode_headers_preset(b: &mut Bencher)2573     fn bench_server_encode_headers_preset(b: &mut Bencher) {
2574         use crate::proto::BodyLength;
2575         use http::header::HeaderValue;
2576 
2577         let len = 108;
2578         b.bytes = len as u64;
2579 
2580         let mut head = MessageHead::default();
2581         let mut headers = HeaderMap::new();
2582         headers.insert("content-length", HeaderValue::from_static("10"));
2583         headers.insert("content-type", HeaderValue::from_static("application/json"));
2584 
2585         b.iter(|| {
2586             let mut vec = Vec::new();
2587             head.headers = headers.clone();
2588             Server::encode(
2589                 Encode {
2590                     head: &mut head,
2591                     body: Some(BodyLength::Known(10)),
2592                     keep_alive: true,
2593                     req_method: &mut Some(Method::GET),
2594                     title_case_headers: false,
2595                 },
2596                 &mut vec,
2597             )
2598             .unwrap();
2599             assert_eq!(vec.len(), len);
2600             ::test::black_box(vec);
2601         })
2602     }
2603 
2604     #[cfg(feature = "nightly")]
2605     #[bench]
bench_server_encode_no_headers(b: &mut Bencher)2606     fn bench_server_encode_no_headers(b: &mut Bencher) {
2607         use crate::proto::BodyLength;
2608 
2609         let len = 76;
2610         b.bytes = len as u64;
2611 
2612         let mut head = MessageHead::default();
2613         let mut vec = Vec::with_capacity(128);
2614 
2615         b.iter(|| {
2616             Server::encode(
2617                 Encode {
2618                     head: &mut head,
2619                     body: Some(BodyLength::Known(10)),
2620                     keep_alive: true,
2621                     req_method: &mut Some(Method::GET),
2622                     title_case_headers: false,
2623                 },
2624                 &mut vec,
2625             )
2626             .unwrap();
2627             assert_eq!(vec.len(), len);
2628             ::test::black_box(&vec);
2629 
2630             vec.clear();
2631         })
2632     }
2633 }
2634