1 // `mem::uninitialized` replaced with `mem::MaybeUninit`,
2 // can't upgrade yet
3 #![allow(deprecated)]
4 
5 use std::fmt::{self, Write};
6 use std::mem;
7 
8 use bytes::{BytesMut};
9 use http::header::{self, Entry, HeaderName, HeaderValue};
10 use http::{HeaderMap, Method, StatusCode, Version};
11 use httparse;
12 
13 use error::Parse;
14 use headers;
15 use proto::{BodyLength, DecodedLength, MessageHead, RequestLine, RequestHead};
16 use proto::h1::{Encode, Encoder, Http1Transaction, ParseResult, ParseContext, ParsedMessage, date};
17 
18 const MAX_HEADERS: usize = 100;
19 const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
20 
21 macro_rules! header_name {
22     ($bytes:expr) => ({
23         #[cfg(debug_assertions)]
24         {
25             match HeaderName::from_bytes($bytes) {
26                 Ok(name) => name,
27                 Err(_) => panic!("illegal header name from httparse: {:?}", ::bytes::Bytes::from($bytes)),
28             }
29         }
30 
31         #[cfg(not(debug_assertions))]
32         {
33             HeaderName::from_bytes($bytes)
34                 .expect("header name validated by httparse")
35         }
36     });
37 }
38 
39 macro_rules! header_value {
40     ($bytes:expr) => ({
41         #[cfg(debug_assertions)]
42         {
43             let __hvb: ::bytes::Bytes = $bytes;
44             match HeaderValue::from_shared(__hvb.clone()) {
45                 Ok(name) => name,
46                 Err(_) => panic!("illegal header value from httparse: {:?}", __hvb),
47             }
48         }
49 
50         #[cfg(not(debug_assertions))]
51         {
52             // Unsafe: httparse already validated header value
53             unsafe {
54                 HeaderValue::from_shared_unchecked($bytes)
55             }
56         }
57     });
58 }
59 
60 // There are 2 main roles, Client and Server.
61 
62 pub(crate) enum Client {}
63 
64 pub(crate) enum Server {}
65 
66 impl Http1Transaction for Server {
67     type Incoming = RequestLine;
68     type Outgoing = StatusCode;
69     const LOG: &'static str = "{role=server}";
70 
parse(buf: &mut BytesMut, ctx: ParseContext) -> ParseResult<RequestLine>71     fn parse(buf: &mut BytesMut, ctx: ParseContext) -> ParseResult<RequestLine> {
72         if buf.is_empty() {
73             return Ok(None);
74         }
75 
76         let mut keep_alive;
77         let is_http_11;
78         let subject;
79         let version;
80         let len;
81         let headers_len;
82 
83         // Unsafe: both headers_indices and headers are using unitialized memory,
84         // but we *never* read any of it until after httparse has assigned
85         // values into it. By not zeroing out the stack memory, this saves
86         // a good ~5% on pipeline benchmarks.
87         let mut headers_indices: [HeaderIndices; MAX_HEADERS] = unsafe { mem::uninitialized() };
88         {
89             let mut headers: [httparse::Header; MAX_HEADERS] = unsafe { mem::uninitialized() };
90             trace!("Request.parse([Header; {}], [u8; {}])", headers.len(), buf.len());
91             let mut req = httparse::Request::new(&mut headers);
92             let bytes = buf.as_ref();
93             match req.parse(bytes) {
94                 Ok(httparse::Status::Complete(parsed_len)) => {
95                     trace!("Request.parse Complete({})", parsed_len);
96                     len = parsed_len;
97                     subject = RequestLine(
98                         Method::from_bytes(req.method.unwrap().as_bytes())?,
99                         req.path.unwrap().parse()?
100                     );
101                     version = if req.version.unwrap() == 1 {
102                         keep_alive = true;
103                         is_http_11 = true;
104                         Version::HTTP_11
105                     } else {
106                         keep_alive = false;
107                         is_http_11 = false;
108                         Version::HTTP_10
109                     };
110 
111                     record_header_indices(bytes, &req.headers, &mut headers_indices)?;
112                     headers_len = req.headers.len();
113                 }
114                 Ok(httparse::Status::Partial) => return Ok(None),
115                 Err(err) => return Err(match err {
116                     // if invalid Token, try to determine if for method or path
117                     httparse::Error::Token => {
118                         if req.method.is_none() {
119                             Parse::Method
120                         } else {
121                             debug_assert!(req.path.is_none());
122                             Parse::Uri
123                         }
124                     },
125                     other => other.into(),
126                 }),
127             }
128         };
129 
130         let slice = buf.split_to(len).freeze();
131 
132         // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
133         // 1. (irrelevant to Request)
134         // 2. (irrelevant to Request)
135         // 3. Transfer-Encoding: chunked has a chunked body.
136         // 4. If multiple differing Content-Length headers or invalid, close connection.
137         // 5. Content-Length header has a sized body.
138         // 6. Length 0.
139         // 7. (irrelevant to Request)
140 
141 
142         let mut decoder = DecodedLength::ZERO;
143         let mut expect_continue = false;
144         let mut con_len = None;
145         let mut is_te = false;
146         let mut is_te_chunked = false;
147         let mut wants_upgrade = subject.0 == Method::CONNECT;
148 
149         let mut headers = ctx.cached_headers
150             .take()
151             .unwrap_or_else(HeaderMap::new);
152 
153         headers.reserve(headers_len);
154 
155         for header in &headers_indices[..headers_len] {
156             let name = header_name!(&slice[header.name.0..header.name.1]);
157             let value = header_value!(slice.slice(header.value.0, header.value.1));
158 
159             match name {
160                 header::TRANSFER_ENCODING => {
161                     // https://tools.ietf.org/html/rfc7230#section-3.3.3
162                     // If Transfer-Encoding header is present, and 'chunked' is
163                     // not the final encoding, and this is a Request, then it is
164                     // mal-formed. A server should respond with 400 Bad Request.
165                     if !is_http_11 {
166                         debug!("HTTP/1.0 cannot have Transfer-Encoding header");
167                         return Err(Parse::Header);
168                     }
169                     is_te = true;
170                     if headers::is_chunked_(&value) {
171                         is_te_chunked = true;
172                         decoder = DecodedLength::CHUNKED;
173                     }
174                 },
175                 header::CONTENT_LENGTH => {
176                     if is_te {
177                         continue;
178                     }
179                     let len = value.to_str()
180                         .map_err(|_| Parse::Header)
181                         .and_then(|s| s.parse().map_err(|_| Parse::Header))?;
182                     if let Some(prev) = con_len {
183                         if prev != len {
184                             debug!(
185                                 "multiple Content-Length headers with different values: [{}, {}]",
186                                 prev,
187                                 len,
188                             );
189                             return Err(Parse::Header);
190                         }
191                         // we don't need to append this secondary length
192                         continue;
193                     }
194                     decoder = DecodedLength::checked_new(len)?;
195                     con_len = Some(len);
196                 },
197                 header::CONNECTION => {
198                     // keep_alive was previously set to default for Version
199                     if keep_alive {
200                         // HTTP/1.1
201                         keep_alive = !headers::connection_close(&value);
202 
203                     } else {
204                         // HTTP/1.0
205                         keep_alive = headers::connection_keep_alive(&value);
206                     }
207                 },
208                 header::EXPECT => {
209                     expect_continue = value.as_bytes() == b"100-continue";
210                 },
211                 header::UPGRADE => {
212                     // Upgrades are only allowed with HTTP/1.1
213                     wants_upgrade = is_http_11;
214                 },
215 
216                 _ => (),
217             }
218 
219             headers.append(name, value);
220         }
221 
222         if is_te && !is_te_chunked {
223             debug!("request with transfer-encoding header, but not chunked, bad request");
224             return Err(Parse::Header);
225         }
226 
227         *ctx.req_method = Some(subject.0.clone());
228 
229         Ok(Some(ParsedMessage {
230             head: MessageHead {
231                 version,
232                 subject,
233                 headers,
234             },
235             decode: decoder,
236             expect_continue,
237             keep_alive,
238             wants_upgrade,
239         }))
240     }
241 
encode(mut msg: Encode<Self::Outgoing>, mut dst: &mut Vec<u8>) -> ::Result<Encoder>242     fn encode(mut msg: Encode<Self::Outgoing>, mut dst: &mut Vec<u8>) -> ::Result<Encoder> {
243         trace!(
244             "Server::encode status={:?}, body={:?}, req_method={:?}",
245             msg.head.subject,
246             msg.body,
247             msg.req_method
248         );
249         debug_assert!(!msg.title_case_headers, "no server config for title case headers");
250 
251         let mut wrote_len = false;
252 
253         // hyper currently doesn't support returning 1xx status codes as a Response
254         // This is because Service only allows returning a single Response, and
255         // so if you try to reply with a e.g. 100 Continue, you have no way of
256         // replying with the latter status code response.
257         let (ret, mut is_last) = if msg.head.subject == StatusCode::SWITCHING_PROTOCOLS {
258             (Ok(()), true)
259         } else if msg.req_method == &Some(Method::CONNECT) && msg.head.subject.is_success() {
260             // Sending content-length or transfer-encoding header on 2xx response
261             // to CONNECT is forbidden in RFC 7231.
262             wrote_len = true;
263             (Ok(()), true)
264         } else if msg.head.subject.is_informational() {
265             warn!("response with 1xx status code not supported");
266             *msg.head = MessageHead::default();
267             msg.head.subject = StatusCode::INTERNAL_SERVER_ERROR;
268             msg.body = None;
269             (Err(::Error::new_user_unsupported_status_code()), true)
270         } else {
271             (Ok(()), !msg.keep_alive)
272         };
273 
274         // In some error cases, we don't know about the invalid message until already
275         // pushing some bytes onto the `dst`. In those cases, we don't want to send
276         // the half-pushed message, so rewind to before.
277         let orig_len = dst.len();
278         let rewind = |dst: &mut Vec<u8>| {
279             dst.truncate(orig_len);
280         };
281 
282         let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
283         dst.reserve(init_cap);
284         if msg.head.version == Version::HTTP_11 && msg.head.subject == StatusCode::OK {
285             extend(dst, b"HTTP/1.1 200 OK\r\n");
286         } else {
287             match msg.head.version {
288                 Version::HTTP_10 => extend(dst, b"HTTP/1.0 "),
289                 Version::HTTP_11 => extend(dst, b"HTTP/1.1 "),
290                 Version::HTTP_2 => {
291                     warn!("response with HTTP2 version coerced to HTTP/1.1");
292                     extend(dst, b"HTTP/1.1 ");
293                 },
294                 other => panic!("unexpected response version: {:?}", other),
295             }
296 
297             extend(dst, msg.head.subject.as_str().as_bytes());
298             extend(dst, b" ");
299             // a reason MUST be written, as many parsers will expect it.
300             extend(dst, msg.head.subject.canonical_reason().unwrap_or("<none>").as_bytes());
301             extend(dst, b"\r\n");
302         }
303 
304         let mut encoder = Encoder::length(0);
305         let mut wrote_date = false;
306         'headers: for (name, mut values) in msg.head.headers.drain() {
307             match name {
308                 header::CONTENT_LENGTH => {
309                     if wrote_len {
310                         warn!("unexpected content-length found, canceling");
311                         rewind(dst);
312                         return Err(::Error::new_user_header());
313                     }
314                     match msg.body {
315                         Some(BodyLength::Known(known_len)) => {
316                             // The Payload claims to know a length, and
317                             // the headers are already set. For performance
318                             // reasons, we are just going to trust that
319                             // the values match.
320                             //
321                             // In debug builds, we'll assert they are the
322                             // same to help developers find bugs.
323                             encoder = Encoder::length(known_len);
324 
325                             #[cfg(debug_assertions)]
326                             {
327                                 let mut folded = None::<(u64, HeaderValue)>;
328                                 for value in values {
329                                     if let Some(len) = headers::content_length_parse(&value) {
330                                         if let Some(fold) = folded {
331                                             if fold.0 != len {
332                                                 panic!("multiple Content-Length values found: [{}, {}]", fold.0, len);
333                                             }
334                                             folded = Some(fold);
335                                         } else {
336                                             folded = Some((len, value));
337                                         }
338                                     } else {
339                                         panic!("illegal Content-Length value: {:?}", value);
340                                     }
341                                 }
342                                 if let Some((len, value)) = folded {
343                                     assert!(
344                                         len == known_len,
345                                         "payload claims content-length of {}, custom content-length header claims {}",
346                                         known_len,
347                                         len,
348                                     );
349                                     extend(dst, b"content-length: ");
350                                     extend(dst, value.as_bytes());
351                                     extend(dst, b"\r\n");
352                                     wrote_len = true;
353                                     continue 'headers;
354                                 } else {
355                                     // No values in content-length... ignore?
356                                     continue 'headers;
357                                 }
358                             }
359                         },
360                         Some(BodyLength::Unknown) => {
361                             // The Payload impl didn't know how long the
362                             // body is, but a length header was included.
363                             // We have to parse the value to return our
364                             // Encoder...
365                             let mut folded = None::<(u64, HeaderValue)>;
366                             for value in values {
367                                 if let Some(len) = headers::content_length_parse(&value) {
368                                     if let Some(fold) = folded {
369                                         if fold.0 != len {
370                                             warn!("multiple Content-Length values found: [{}, {}]", fold.0, len);
371                                             rewind(dst);
372                                             return Err(::Error::new_user_header());
373                                         }
374                                         folded = Some(fold);
375                                     } else {
376                                         folded = Some((len, value));
377                                     }
378                                 } else {
379                                     warn!("illegal Content-Length value: {:?}", value);
380                                     rewind(dst);
381                                     return Err(::Error::new_user_header());
382                                 }
383                             }
384                             if let Some((len, value)) = folded {
385                                 encoder = Encoder::length(len);
386                                 extend(dst, b"content-length: ");
387                                 extend(dst, value.as_bytes());
388                                 extend(dst, b"\r\n");
389                                 wrote_len = true;
390                                 continue 'headers;
391                             } else {
392                                 // No values in content-length... ignore?
393                                 continue 'headers;
394                             }
395                         },
396                         None => {
397                             // We have no body to actually send,
398                             // but the headers claim a content-length.
399                             // There's only 2 ways this makes sense:
400                             //
401                             // - The header says the length is `0`.
402                             // - This is a response to a `HEAD` request.
403                             if msg.req_method == &Some(Method::HEAD) {
404                                 debug_assert_eq!(encoder, Encoder::length(0));
405                             } else {
406                                 for value in values {
407                                     if value.as_bytes() != b"0" {
408                                         warn!("content-length value found, but empty body provided: {:?}", value);
409                                     }
410                                 }
411                                 continue 'headers;
412                             }
413                         }
414                     }
415                     wrote_len = true;
416                 },
417                 header::TRANSFER_ENCODING => {
418                     if wrote_len {
419                         warn!("unexpected transfer-encoding found, canceling");
420                         rewind(dst);
421                         return Err(::Error::new_user_header());
422                     }
423                     // check that we actually can send a chunked body...
424                     if msg.head.version == Version::HTTP_10 || !Server::can_chunked(msg.req_method, msg.head.subject) {
425                         continue;
426                     }
427                     wrote_len = true;
428                     encoder = Encoder::chunked();
429 
430                     extend(dst, b"transfer-encoding: ");
431 
432                     let mut saw_chunked;
433                     if let Some(te) = values.next() {
434                         extend(dst, te.as_bytes());
435                         saw_chunked = headers::is_chunked_(&te);
436                         for value in values {
437                             extend(dst, b", ");
438                             extend(dst, value.as_bytes());
439                             saw_chunked = headers::is_chunked_(&value);
440                         }
441                         if !saw_chunked {
442                             extend(dst, b", chunked\r\n");
443                         } else {
444                             extend(dst, b"\r\n");
445                         }
446                     } else {
447                         // zero lines? add a chunked line then
448                         extend(dst, b"chunked\r\n");
449                     }
450                     continue 'headers;
451                 },
452                 header::CONNECTION => {
453                     if !is_last {
454                         for value in values {
455                             extend(dst, name.as_str().as_bytes());
456                             extend(dst, b": ");
457                             extend(dst, value.as_bytes());
458                             extend(dst, b"\r\n");
459 
460                             if headers::connection_close(&value) {
461                                 is_last = true;
462                             }
463                         }
464                         continue 'headers;
465                     }
466                 },
467                 header::DATE => {
468                     wrote_date = true;
469                 },
470                 _ => (),
471             }
472             //TODO: this should perhaps instead combine them into
473             //single lines, as RFC7230 suggests is preferable.
474             for value in values {
475                 extend(dst, name.as_str().as_bytes());
476                 extend(dst, b": ");
477                 extend(dst, value.as_bytes());
478                 extend(dst, b"\r\n");
479             }
480         }
481 
482         if !wrote_len {
483             encoder = match msg.body {
484                 Some(BodyLength::Unknown) => {
485                     if msg.head.version == Version::HTTP_10 || !Server::can_chunked(msg.req_method, msg.head.subject) {
486                         Encoder::close_delimited()
487                     } else {
488                         extend(dst, b"transfer-encoding: chunked\r\n");
489                         Encoder::chunked()
490                     }
491                 },
492                 None |
493                 Some(BodyLength::Known(0)) => {
494                     if msg.head.subject != StatusCode::NOT_MODIFIED {
495                         extend(dst, b"content-length: 0\r\n");
496                     }
497                     Encoder::length(0)
498                 },
499                 Some(BodyLength::Known(len)) => {
500                     if msg.head.subject == StatusCode::NOT_MODIFIED {
501                         Encoder::length(0)
502                     } else {
503                         extend(dst, b"content-length: ");
504                         let _ = ::itoa::write(&mut dst, len);
505                         extend(dst, b"\r\n");
506                         Encoder::length(len)
507                     }
508                 },
509             };
510         }
511 
512         if !Server::can_have_body(msg.req_method, msg.head.subject) {
513             trace!(
514                 "server body forced to 0; method={:?}, status={:?}",
515                 msg.req_method,
516                 msg.head.subject
517             );
518             encoder = Encoder::length(0);
519         }
520 
521         // cached date is much faster than formatting every request
522         if !wrote_date {
523             dst.reserve(date::DATE_VALUE_LENGTH + 8);
524             extend(dst, b"date: ");
525             date::extend(dst);
526             extend(dst, b"\r\n\r\n");
527         } else {
528             extend(dst, b"\r\n");
529         }
530 
531         ret.map(|()| encoder.set_last(is_last))
532     }
533 
on_error(err: &::Error) -> Option<MessageHead<Self::Outgoing>>534     fn on_error(err: &::Error) -> Option<MessageHead<Self::Outgoing>> {
535         use ::error::Kind;
536         let status = match *err.kind() {
537             Kind::Parse(Parse::Method) |
538             Kind::Parse(Parse::Header) |
539             Kind::Parse(Parse::Uri)    |
540             Kind::Parse(Parse::Version) => {
541                 StatusCode::BAD_REQUEST
542             },
543             Kind::Parse(Parse::TooLarge) => {
544                 StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE
545             },
546             _ => return None,
547         };
548 
549         debug!("sending automatic response ({}) for parse error", status);
550         let mut msg = MessageHead::default();
551         msg.subject = status;
552         Some(msg)
553     }
554 
is_server() -> bool555     fn is_server() -> bool {
556         true
557     }
558 
update_date()559     fn update_date() {
560         date::update();
561     }
562 }
563 
564 impl Server {
can_have_body(method: &Option<Method>, status: StatusCode) -> bool565     fn can_have_body(method: &Option<Method>, status: StatusCode) -> bool {
566         Server::can_chunked(method, status)
567     }
568 
can_chunked(method: &Option<Method>, status: StatusCode) -> bool569     fn can_chunked(method: &Option<Method>, status: StatusCode) -> bool {
570         if method == &Some(Method::HEAD) {
571             false
572         } else if method == &Some(Method::CONNECT) && status.is_success() {
573             false
574         } else {
575             match status {
576                 // TODO: support for 1xx codes needs improvement everywhere
577                 // would be 100...199 => false
578                 StatusCode::SWITCHING_PROTOCOLS |
579                 StatusCode::NO_CONTENT |
580                 StatusCode::NOT_MODIFIED => false,
581                 _ => true,
582             }
583         }
584     }
585 }
586 
587 impl Http1Transaction for Client {
588     type Incoming = StatusCode;
589     type Outgoing = RequestLine;
590     const LOG: &'static str = "{role=client}";
591 
parse(buf: &mut BytesMut, ctx: ParseContext) -> ParseResult<StatusCode>592     fn parse(buf: &mut BytesMut, ctx: ParseContext) -> ParseResult<StatusCode> {
593         // Loop to skip information status code headers (100 Continue, etc).
594         loop {
595             if buf.is_empty() {
596                 return Ok(None);
597             }
598             // Unsafe: see comment in Server Http1Transaction, above.
599             let mut headers_indices: [HeaderIndices; MAX_HEADERS] = unsafe { mem::uninitialized() };
600             let (len, status, version, headers_len) = {
601                 let mut headers: [httparse::Header; MAX_HEADERS] = unsafe { mem::uninitialized() };
602                 trace!("Response.parse([Header; {}], [u8; {}])", headers.len(), buf.len());
603                 let mut res = httparse::Response::new(&mut headers);
604                 let bytes = buf.as_ref();
605                 match res.parse(bytes)? {
606                     httparse::Status::Complete(len) => {
607                         trace!("Response.parse Complete({})", len);
608                         let status = StatusCode::from_u16(res.code.unwrap())?;
609                         let version = if res.version.unwrap() == 1 {
610                             Version::HTTP_11
611                         } else {
612                             Version::HTTP_10
613                         };
614                         record_header_indices(bytes, &res.headers, &mut headers_indices)?;
615                         let headers_len = res.headers.len();
616                         (len, status, version, headers_len)
617                     },
618                     httparse::Status::Partial => return Ok(None),
619                 }
620             };
621 
622             let slice = buf.split_to(len).freeze();
623 
624             let mut headers = ctx.cached_headers
625                 .take()
626                 .unwrap_or_else(HeaderMap::new);
627 
628             let mut keep_alive = version == Version::HTTP_11;
629 
630             headers.reserve(headers_len);
631             for header in &headers_indices[..headers_len] {
632                 let name = header_name!(&slice[header.name.0..header.name.1]);
633                 let value = header_value!(slice.slice(header.value.0, header.value.1));
634 
635                 if let header::CONNECTION = name {
636                     // keep_alive was previously set to default for Version
637                         if keep_alive {
638                             // HTTP/1.1
639                             keep_alive = !headers::connection_close(&value);
640 
641                         } else {
642                             // HTTP/1.0
643                             keep_alive = headers::connection_keep_alive(&value);
644                         }
645                     }
646                 headers.append(name, value);
647             }
648 
649             let head = MessageHead {
650                 version,
651                 subject: status,
652                 headers,
653             };
654             if let Some((decode, is_upgrade)) = Client::decoder(&head, ctx.req_method)? {
655                 return Ok(Some(ParsedMessage {
656                     head,
657                     decode,
658                     expect_continue: false,
659                     // a client upgrade means the connection can't be used
660                     // again, as it is definitely upgrading.
661                     keep_alive: keep_alive && !is_upgrade,
662                     wants_upgrade: is_upgrade,
663                 }));
664             }
665 
666         }
667     }
668 
encode(msg: Encode<Self::Outgoing>, dst: &mut Vec<u8>) -> ::Result<Encoder>669     fn encode(msg: Encode<Self::Outgoing>, dst: &mut Vec<u8>) -> ::Result<Encoder> {
670         trace!("Client::encode method={:?}, body={:?}", msg.head.subject.0, msg.body);
671 
672         *msg.req_method = Some(msg.head.subject.0.clone());
673 
674         let body = Client::set_length(msg.head, msg.body);
675 
676         let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
677         dst.reserve(init_cap);
678 
679 
680         extend(dst, msg.head.subject.0.as_str().as_bytes());
681         extend(dst, b" ");
682         //TODO: add API to http::Uri to encode without std::fmt
683         let _ = write!(FastWrite(dst), "{} ", msg.head.subject.1);
684 
685         match msg.head.version {
686             Version::HTTP_10 => extend(dst, b"HTTP/1.0"),
687             Version::HTTP_11 => extend(dst, b"HTTP/1.1"),
688             Version::HTTP_2 => {
689                 warn!("request with HTTP2 version coerced to HTTP/1.1");
690                 extend(dst, b"HTTP/1.1");
691             },
692             other => panic!("unexpected request version: {:?}", other),
693         }
694         extend(dst, b"\r\n");
695 
696         if msg.title_case_headers {
697             write_headers_title_case(&msg.head.headers, dst);
698         } else {
699             write_headers(&msg.head.headers, dst);
700         }
701         extend(dst, b"\r\n");
702         msg.head.headers.clear(); //TODO: remove when switching to drain()
703 
704         Ok(body)
705     }
706 
on_error(_err: &::Error) -> Option<MessageHead<Self::Outgoing>>707     fn on_error(_err: &::Error) -> Option<MessageHead<Self::Outgoing>> {
708         // we can't tell the server about any errors it creates
709         None
710     }
711 
is_client() -> bool712     fn is_client() -> bool {
713         true
714     }
715 }
716 
717 impl Client {
718     /// Returns Some(length, wants_upgrade) if successful.
719     ///
720     /// 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>721     fn decoder(inc: &MessageHead<StatusCode>, method: &mut Option<Method>) -> Result<Option<(DecodedLength, bool)>, Parse> {
722         // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
723         // 1. HEAD responses, and Status 1xx, 204, and 304 cannot have a body.
724         // 2. Status 2xx to a CONNECT cannot have a body.
725         // 3. Transfer-Encoding: chunked has a chunked body.
726         // 4. If multiple differing Content-Length headers or invalid, close connection.
727         // 5. Content-Length header has a sized body.
728         // 6. (irrelevant to Response)
729         // 7. Read till EOF.
730 
731         match inc.subject.as_u16() {
732             101 => {
733                 return Ok(Some((DecodedLength::ZERO, true)));
734             },
735             100..=199 => {
736                 trace!("ignoring informational response: {}", inc.subject.as_u16());
737                 return Ok(None);
738             },
739             204 |
740             304 => return Ok(Some((DecodedLength::ZERO, false))),
741             _ => (),
742         }
743         match *method {
744             Some(Method::HEAD) => {
745                 return Ok(Some((DecodedLength::ZERO, false)));
746             }
747             Some(Method::CONNECT) => if let 200..=299 = inc.subject.as_u16() {
748                 return Ok(Some((DecodedLength::ZERO, true)));
749             }
750             Some(_) => {},
751             None => {
752                 trace!("Client::decoder is missing the Method");
753             }
754         }
755 
756         if inc.headers.contains_key(header::TRANSFER_ENCODING) {
757             // https://tools.ietf.org/html/rfc7230#section-3.3.3
758             // If Transfer-Encoding header is present, and 'chunked' is
759             // not the final encoding, and this is a Request, then it is
760             // mal-formed. A server should respond with 400 Bad Request.
761             if inc.version == Version::HTTP_10 {
762                 debug!("HTTP/1.0 cannot have Transfer-Encoding header");
763                 Err(Parse::Header)
764             } else if headers::transfer_encoding_is_chunked(&inc.headers) {
765                 Ok(Some((DecodedLength::CHUNKED, false)))
766             } else {
767                 trace!("not chunked, read till eof");
768                 Ok(Some((DecodedLength::CHUNKED, false)))
769             }
770         } else if let Some(len) = headers::content_length_parse_all(&inc.headers) {
771             Ok(Some((DecodedLength::checked_new(len)?, false)))
772         } else if inc.headers.contains_key(header::CONTENT_LENGTH) {
773             debug!("illegal Content-Length header");
774             Err(Parse::Header)
775         } else {
776             trace!("neither Transfer-Encoding nor Content-Length");
777             Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
778         }
779     }
780 }
781 
782 impl Client {
set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder783     fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
784         let body = if let Some(body) = body {
785             body
786         } else {
787             head.headers.remove(header::TRANSFER_ENCODING);
788             return Encoder::length(0)
789         };
790 
791         // HTTP/1.0 doesn't know about chunked
792         let can_chunked = head.version == Version::HTTP_11;
793         let headers = &mut head.headers;
794 
795         // If the user already set specific headers, we should respect them, regardless
796         // of what the Payload knows about itself. They set them for a reason.
797 
798         // Because of the borrow checker, we can't check the for an existing
799         // Content-Length header while holding an `Entry` for the Transfer-Encoding
800         // header, so unfortunately, we must do the check here, first.
801 
802         let existing_con_len = headers::content_length_parse_all(headers);
803         let mut should_remove_con_len = false;
804 
805         if !can_chunked {
806             // Chunked isn't legal, so if it is set, we need to remove it.
807             if headers.remove(header::TRANSFER_ENCODING).is_some() {
808                 trace!("removing illegal transfer-encoding header");
809             }
810 
811             return if let Some(len) = existing_con_len {
812                 Encoder::length(len)
813             } else if let BodyLength::Known(len) = body {
814                 set_content_length(headers, len)
815             } else {
816                 // HTTP/1.0 client requests without a content-length
817                 // cannot have any body at all.
818                 Encoder::length(0)
819             };
820         }
821 
822         // If the user set a transfer-encoding, respect that. Let's just
823         // make sure `chunked` is the final encoding.
824         let encoder = match headers.entry(header::TRANSFER_ENCODING)
825             .expect("TRANSFER_ENCODING is valid HeaderName") {
826             Entry::Occupied(te) => {
827                 should_remove_con_len = true;
828                 if headers::is_chunked(te.iter()) {
829                     Some(Encoder::chunked())
830                 } else {
831                     warn!("user provided transfer-encoding does not end in 'chunked'");
832 
833                     // There's a Transfer-Encoding, but it doesn't end in 'chunked'!
834                     // An example that could trigger this:
835                     //
836                     //     Transfer-Encoding: gzip
837                     //
838                     // This can be bad, depending on if this is a request or a
839                     // response.
840                     //
841                     // - A request is illegal if there is a `Transfer-Encoding`
842                     //   but it doesn't end in `chunked`.
843                     // - A response that has `Transfer-Encoding` but doesn't
844                     //   end in `chunked` isn't illegal, it just forces this
845                     //   to be close-delimited.
846                     //
847                     // We can try to repair this, by adding `chunked` ourselves.
848 
849                     headers::add_chunked(te);
850                     Some(Encoder::chunked())
851                 }
852             },
853             Entry::Vacant(te) => {
854                 if let Some(len) = existing_con_len {
855                     Some(Encoder::length(len))
856                 } else if let BodyLength::Unknown = body {
857                     // GET, HEAD, and CONNECT almost never have bodies.
858                     //
859                     // So instead of sending a "chunked" body with a 0-chunk,
860                     // assume no body here. If you *must* send a body,
861                     // set the headers explicitly.
862                     match head.subject.0 {
863                         Method::GET |
864                         Method::HEAD |
865                         Method::CONNECT => {
866                             Some(Encoder::length(0))
867                         },
868                         _ => {
869                             te.insert(HeaderValue::from_static("chunked"));
870                             Some(Encoder::chunked())
871                         },
872                     }
873                 } else {
874                     None
875                 }
876             },
877         };
878 
879         // This is because we need a second mutable borrow to remove
880         // content-length header.
881         if let Some(encoder) = encoder {
882             if should_remove_con_len && existing_con_len.is_some() {
883                 headers.remove(header::CONTENT_LENGTH);
884             }
885             return encoder;
886         }
887 
888         // User didn't set transfer-encoding, AND we know body length,
889         // so we can just set the Content-Length automatically.
890 
891         let len = if let BodyLength::Known(len) = body {
892             len
893         } else {
894             unreachable!("BodyLength::Unknown would set chunked");
895         };
896 
897         set_content_length(headers, len)
898     }
899 }
900 
set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder901 fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
902     // At this point, there should not be a valid Content-Length
903     // header. However, since we'll be indexing in anyways, we can
904     // warn the user if there was an existing illegal header.
905     //
906     // Or at least, we can in theory. It's actually a little bit slower,
907     // so perhaps only do that while the user is developing/testing.
908 
909     if cfg!(debug_assertions) {
910         match headers.entry(header::CONTENT_LENGTH)
911             .expect("CONTENT_LENGTH is valid HeaderName") {
912             Entry::Occupied(mut cl) => {
913                 // Internal sanity check, we should have already determined
914                 // that the header was illegal before calling this function.
915                 debug_assert!(headers::content_length_parse_all_values(cl.iter()).is_none());
916                 // Uh oh, the user set `Content-Length` headers, but set bad ones.
917                 // This would be an illegal message anyways, so let's try to repair
918                 // with our known good length.
919                 error!("user provided content-length header was invalid");
920 
921                 cl.insert(HeaderValue::from(len));
922                 Encoder::length(len)
923             },
924             Entry::Vacant(cl) => {
925                 cl.insert(HeaderValue::from(len));
926                 Encoder::length(len)
927             }
928         }
929     } else {
930         headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
931         Encoder::length(len)
932     }
933 }
934 
935 #[derive(Clone, Copy)]
936 struct HeaderIndices {
937     name: (usize, usize),
938     value: (usize, usize),
939 }
940 
record_header_indices( bytes: &[u8], headers: &[httparse::Header], indices: &mut [HeaderIndices] ) -> Result<(), ::error::Parse>941 fn record_header_indices(
942     bytes: &[u8],
943     headers: &[httparse::Header],
944     indices: &mut [HeaderIndices]
945 ) -> Result<(), ::error::Parse> {
946     let bytes_ptr = bytes.as_ptr() as usize;
947 
948     // FIXME: This should be a single plain `for` loop.
949     // Splitting it is a work-around for https://github.com/rust-lang/rust/issues/55105
950     macro_rules! split_loops_if {
951         (
952             cfg($($cfg: tt)+)
953             for $i: pat in ($iter: expr) {
954                 $body1: block
955                 $body2: block
956             }
957         ) => {
958             for $i in $iter {
959                 $body1
960                 #[cfg(not($($cfg)+))] $body2
961             }
962             #[cfg($($cfg)+)]
963             for $i in $iter {
964                 $body2
965             }
966         }
967     }
968     split_loops_if! {
969         cfg(all(target_arch = "arm", target_feature = "v7", target_feature = "neon"))
970         for (header, indices) in (headers.iter().zip(indices.iter_mut())) {
971             {
972                 if header.name.len() >= (1 << 16) {
973                     debug!("header name larger than 64kb: {:?}", header.name);
974                     return Err(::error::Parse::TooLarge);
975                 }
976                 let name_start = header.name.as_ptr() as usize - bytes_ptr;
977                 let name_end = name_start + header.name.len();
978                 indices.name = (name_start, name_end);
979             }
980             {
981                 let value_start = header.value.as_ptr() as usize - bytes_ptr;
982                 let value_end = value_start + header.value.len();
983                 indices.value = (value_start, value_end);
984             }
985         }
986     }
987 
988     Ok(())
989 }
990 
991 // Write header names as title case. The header name is assumed to be ASCII,
992 // therefore it is trivial to convert an ASCII character from lowercase to
993 // uppercase. It is as simple as XORing the lowercase character byte with
994 // space.
title_case(dst: &mut Vec<u8>, name: &[u8])995 fn title_case(dst: &mut Vec<u8>, name: &[u8]) {
996     dst.reserve(name.len());
997 
998     let mut iter = name.iter();
999 
1000     // Uppercase the first character
1001     if let Some(c) = iter.next() {
1002         if *c >= b'a' && *c <= b'z' {
1003             dst.push(*c ^ b' ');
1004         } else {
1005             dst.push(*c);
1006         }
1007     }
1008 
1009     while let Some(c) = iter.next() {
1010       dst.push(*c);
1011 
1012       if *c == b'-' {
1013           if let Some(c) = iter.next() {
1014               if *c >= b'a' && *c <= b'z' {
1015                   dst.push(*c ^ b' ');
1016               } else {
1017                   dst.push(*c);
1018               }
1019           }
1020       }
1021     }
1022 }
1023 
write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>)1024 fn write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>) {
1025     for (name, value) in headers {
1026         title_case(dst, name.as_str().as_bytes());
1027         extend(dst, b": ");
1028         extend(dst, value.as_bytes());
1029         extend(dst, b"\r\n");
1030     }
1031 }
1032 
write_headers(headers: &HeaderMap, dst: &mut Vec<u8>)1033 fn write_headers(headers: &HeaderMap, dst: &mut Vec<u8>) {
1034     for (name, value) in headers {
1035         extend(dst, name.as_str().as_bytes());
1036         extend(dst, b": ");
1037         extend(dst, value.as_bytes());
1038         extend(dst, b"\r\n");
1039     }
1040 }
1041 
1042 struct FastWrite<'a>(&'a mut Vec<u8>);
1043 
1044 impl<'a> fmt::Write for FastWrite<'a> {
1045     #[inline]
write_str(&mut self, s: &str) -> fmt::Result1046     fn write_str(&mut self, s: &str) -> fmt::Result {
1047         extend(self.0, s.as_bytes());
1048         Ok(())
1049     }
1050 
1051     #[inline]
write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result1052     fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
1053         fmt::write(self, args)
1054     }
1055 }
1056 
1057 #[inline]
extend(dst: &mut Vec<u8>, data: &[u8])1058 fn extend(dst: &mut Vec<u8>, data: &[u8]) {
1059     dst.extend_from_slice(data);
1060 }
1061 
1062 #[cfg(test)]
1063 mod tests {
1064     use bytes::BytesMut;
1065 
1066     use super::*;
1067 
1068     #[test]
test_parse_request()1069     fn test_parse_request() {
1070         extern crate pretty_env_logger;
1071         let _ = pretty_env_logger::try_init();
1072         let mut raw = BytesMut::from(b"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n".to_vec());
1073         let mut method = None;
1074         let msg = Server::parse(&mut raw, ParseContext {
1075             cached_headers: &mut None,
1076             req_method: &mut method,
1077         }).unwrap().unwrap();
1078         assert_eq!(raw.len(), 0);
1079         assert_eq!(msg.head.subject.0, ::Method::GET);
1080         assert_eq!(msg.head.subject.1, "/echo");
1081         assert_eq!(msg.head.version, ::Version::HTTP_11);
1082         assert_eq!(msg.head.headers.len(), 1);
1083         assert_eq!(msg.head.headers["Host"], "hyper.rs");
1084         assert_eq!(method, Some(::Method::GET));
1085     }
1086 
1087 
1088     #[test]
test_parse_response()1089     fn test_parse_response() {
1090         extern crate pretty_env_logger;
1091         let _ = pretty_env_logger::try_init();
1092         let mut raw = BytesMut::from(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".to_vec());
1093         let ctx = ParseContext {
1094             cached_headers: &mut None,
1095             req_method: &mut Some(::Method::GET),
1096         };
1097         let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1098         assert_eq!(raw.len(), 0);
1099         assert_eq!(msg.head.subject, ::StatusCode::OK);
1100         assert_eq!(msg.head.version, ::Version::HTTP_11);
1101         assert_eq!(msg.head.headers.len(), 1);
1102         assert_eq!(msg.head.headers["Content-Length"], "0");
1103     }
1104 
1105     #[test]
test_parse_request_errors()1106     fn test_parse_request_errors() {
1107         let mut raw = BytesMut::from(b"GET htt:p// HTTP/1.1\r\nHost: hyper.rs\r\n\r\n".to_vec());
1108         let ctx = ParseContext {
1109             cached_headers: &mut None,
1110             req_method: &mut None,
1111         };
1112         Server::parse(&mut raw, ctx).unwrap_err();
1113     }
1114 
1115 
1116     #[test]
test_decoder_request()1117     fn test_decoder_request() {
1118         fn parse(s: &str) -> ParsedMessage<RequestLine> {
1119             let mut bytes = BytesMut::from(s);
1120             Server::parse(&mut bytes, ParseContext {
1121                 cached_headers: &mut None,
1122                 req_method: &mut None,
1123             })
1124                 .expect("parse ok")
1125                 .expect("parse complete")
1126         }
1127 
1128         fn parse_err(s: &str, comment: &str) -> ::error::Parse {
1129             let mut bytes = BytesMut::from(s);
1130             Server::parse(&mut bytes, ParseContext {
1131                 cached_headers: &mut None,
1132                 req_method: &mut None,
1133             })
1134                 .expect_err(comment)
1135         }
1136 
1137         // no length or transfer-encoding means 0-length body
1138         assert_eq!(parse("\
1139             GET / HTTP/1.1\r\n\
1140             \r\n\
1141         ").decode, DecodedLength::ZERO);
1142 
1143         assert_eq!(parse("\
1144             POST / HTTP/1.1\r\n\
1145             \r\n\
1146         ").decode, DecodedLength::ZERO);
1147 
1148         // transfer-encoding: chunked
1149         assert_eq!(parse("\
1150             POST / HTTP/1.1\r\n\
1151             transfer-encoding: chunked\r\n\
1152             \r\n\
1153         ").decode, DecodedLength::CHUNKED);
1154 
1155         assert_eq!(parse("\
1156             POST / HTTP/1.1\r\n\
1157             transfer-encoding: gzip, chunked\r\n\
1158             \r\n\
1159         ").decode, DecodedLength::CHUNKED);
1160 
1161         assert_eq!(parse("\
1162             POST / HTTP/1.1\r\n\
1163             transfer-encoding: gzip\r\n\
1164             transfer-encoding: chunked\r\n\
1165             \r\n\
1166         ").decode, DecodedLength::CHUNKED);
1167 
1168         // content-length
1169         assert_eq!(parse("\
1170             POST / HTTP/1.1\r\n\
1171             content-length: 10\r\n\
1172             \r\n\
1173         ").decode, DecodedLength::new(10));
1174 
1175         // transfer-encoding and content-length = chunked
1176         assert_eq!(parse("\
1177             POST / HTTP/1.1\r\n\
1178             content-length: 10\r\n\
1179             transfer-encoding: chunked\r\n\
1180             \r\n\
1181         ").decode, DecodedLength::CHUNKED);
1182 
1183         assert_eq!(parse("\
1184             POST / HTTP/1.1\r\n\
1185             transfer-encoding: chunked\r\n\
1186             content-length: 10\r\n\
1187             \r\n\
1188         ").decode, DecodedLength::CHUNKED);
1189 
1190         assert_eq!(parse("\
1191             POST / HTTP/1.1\r\n\
1192             transfer-encoding: gzip\r\n\
1193             content-length: 10\r\n\
1194             transfer-encoding: chunked\r\n\
1195             \r\n\
1196         ").decode, DecodedLength::CHUNKED);
1197 
1198 
1199         // multiple content-lengths of same value are fine
1200         assert_eq!(parse("\
1201             POST / HTTP/1.1\r\n\
1202             content-length: 10\r\n\
1203             content-length: 10\r\n\
1204             \r\n\
1205         ").decode, DecodedLength::new(10));
1206 
1207 
1208         // multiple content-lengths with different values is an error
1209         parse_err("\
1210             POST / HTTP/1.1\r\n\
1211             content-length: 10\r\n\
1212             content-length: 11\r\n\
1213             \r\n\
1214         ", "multiple content-lengths");
1215 
1216         // transfer-encoding that isn't chunked is an error
1217         parse_err("\
1218             POST / HTTP/1.1\r\n\
1219             transfer-encoding: gzip\r\n\
1220             \r\n\
1221         ", "transfer-encoding but not chunked");
1222 
1223         parse_err("\
1224             POST / HTTP/1.1\r\n\
1225             transfer-encoding: chunked, gzip\r\n\
1226             \r\n\
1227         ", "transfer-encoding doesn't end in chunked");
1228 
1229 
1230         // http/1.0
1231 
1232         assert_eq!(parse("\
1233             POST / HTTP/1.0\r\n\
1234             content-length: 10\r\n\
1235             \r\n\
1236         ").decode, DecodedLength::new(10));
1237 
1238 
1239         // 1.0 doesn't understand chunked, so its an error
1240         parse_err("\
1241             POST / HTTP/1.0\r\n\
1242             transfer-encoding: chunked\r\n\
1243             \r\n\
1244         ", "1.0 chunked");
1245     }
1246 
1247     #[test]
test_decoder_response()1248     fn test_decoder_response() {
1249 
1250         fn parse(s: &str) -> ParsedMessage<StatusCode> {
1251             parse_with_method(s, Method::GET)
1252         }
1253 
1254         fn parse_ignores(s: &str) {
1255             let mut bytes = BytesMut::from(s);
1256             assert!(Client::parse(&mut bytes, ParseContext {
1257                 cached_headers: &mut None,
1258                 req_method: &mut Some(Method::GET),
1259             })
1260                 .expect("parse ok")
1261                 .is_none())
1262         }
1263 
1264         fn parse_with_method(s: &str, m: Method) -> ParsedMessage<StatusCode> {
1265             let mut bytes = BytesMut::from(s);
1266             Client::parse(&mut bytes, ParseContext {
1267                 cached_headers: &mut None,
1268                 req_method: &mut Some(m),
1269             })
1270                 .expect("parse ok")
1271                 .expect("parse complete")
1272         }
1273 
1274         fn parse_err(s: &str) -> ::error::Parse {
1275             let mut bytes = BytesMut::from(s);
1276             Client::parse(&mut bytes, ParseContext {
1277                 cached_headers: &mut None,
1278                 req_method: &mut Some(Method::GET),
1279             })
1280                 .expect_err("parse should err")
1281         }
1282 
1283 
1284         // no content-length or transfer-encoding means close-delimited
1285         assert_eq!(parse("\
1286             HTTP/1.1 200 OK\r\n\
1287             \r\n\
1288         ").decode, DecodedLength::CLOSE_DELIMITED);
1289 
1290         // 204 and 304 never have a body
1291         assert_eq!(parse("\
1292             HTTP/1.1 204 No Content\r\n\
1293             \r\n\
1294         ").decode, DecodedLength::ZERO);
1295 
1296         assert_eq!(parse("\
1297             HTTP/1.1 304 Not Modified\r\n\
1298             \r\n\
1299         ").decode, DecodedLength::ZERO);
1300 
1301         // content-length
1302         assert_eq!(parse("\
1303             HTTP/1.1 200 OK\r\n\
1304             content-length: 8\r\n\
1305             \r\n\
1306         ").decode, DecodedLength::new(8));
1307 
1308         assert_eq!(parse("\
1309             HTTP/1.1 200 OK\r\n\
1310             content-length: 8\r\n\
1311             content-length: 8\r\n\
1312             \r\n\
1313         ").decode, DecodedLength::new(8));
1314 
1315         parse_err("\
1316             HTTP/1.1 200 OK\r\n\
1317             content-length: 8\r\n\
1318             content-length: 9\r\n\
1319             \r\n\
1320         ");
1321 
1322 
1323         // transfer-encoding
1324         assert_eq!(parse("\
1325             HTTP/1.1 200 OK\r\n\
1326             transfer-encoding: chunked\r\n\
1327             \r\n\
1328         ").decode, DecodedLength::CHUNKED);
1329 
1330         // transfer-encoding and content-length = chunked
1331         assert_eq!(parse("\
1332             HTTP/1.1 200 OK\r\n\
1333             content-length: 10\r\n\
1334             transfer-encoding: chunked\r\n\
1335             \r\n\
1336         ").decode, DecodedLength::CHUNKED);
1337 
1338 
1339         // HEAD can have content-length, but not body
1340         assert_eq!(parse_with_method("\
1341             HTTP/1.1 200 OK\r\n\
1342             content-length: 8\r\n\
1343             \r\n\
1344         ", Method::HEAD).decode, DecodedLength::ZERO);
1345 
1346         // CONNECT with 200 never has body
1347         {
1348             let msg = parse_with_method("\
1349                 HTTP/1.1 200 OK\r\n\
1350                 \r\n\
1351             ", Method::CONNECT);
1352             assert_eq!(msg.decode, DecodedLength::ZERO);
1353             assert!(!msg.keep_alive, "should be upgrade");
1354             assert!(msg.wants_upgrade, "should be upgrade");
1355         }
1356 
1357         // CONNECT receiving non 200 can have a body
1358         assert_eq!(parse_with_method("\
1359             HTTP/1.1 400 Bad Request\r\n\
1360             \r\n\
1361         ", Method::CONNECT).decode, DecodedLength::CLOSE_DELIMITED);
1362 
1363 
1364         // 1xx status codes
1365         parse_ignores("\
1366             HTTP/1.1 100 Continue\r\n\
1367             \r\n\
1368         ");
1369 
1370         parse_ignores("\
1371             HTTP/1.1 103 Early Hints\r\n\
1372             \r\n\
1373         ");
1374 
1375         // 101 upgrade not supported yet
1376         {
1377             let msg = parse("\
1378                 HTTP/1.1 101 Switching Protocols\r\n\
1379                 \r\n\
1380             ");
1381             assert_eq!(msg.decode, DecodedLength::ZERO);
1382             assert!(!msg.keep_alive, "should be last");
1383             assert!(msg.wants_upgrade, "should be upgrade");
1384         }
1385 
1386 
1387         // http/1.0
1388         assert_eq!(parse("\
1389             HTTP/1.0 200 OK\r\n\
1390             \r\n\
1391         ").decode, DecodedLength::CLOSE_DELIMITED);
1392 
1393         // 1.0 doesn't understand chunked
1394         parse_err("\
1395             HTTP/1.0 200 OK\r\n\
1396             transfer-encoding: chunked\r\n\
1397             \r\n\
1398         ");
1399 
1400         // keep-alive
1401         assert!(parse("\
1402             HTTP/1.1 200 OK\r\n\
1403             content-length: 0\r\n\
1404             \r\n\
1405         ").keep_alive, "HTTP/1.1 keep-alive is default");
1406 
1407         assert!(!parse("\
1408             HTTP/1.1 200 OK\r\n\
1409             content-length: 0\r\n\
1410             connection: foo, close, bar\r\n\
1411             \r\n\
1412         ").keep_alive, "connection close is always close");
1413 
1414         assert!(!parse("\
1415             HTTP/1.0 200 OK\r\n\
1416             content-length: 0\r\n\
1417             \r\n\
1418         ").keep_alive, "HTTP/1.0 close is default");
1419 
1420         assert!(parse("\
1421             HTTP/1.0 200 OK\r\n\
1422             content-length: 0\r\n\
1423             connection: foo, keep-alive, bar\r\n\
1424             \r\n\
1425         ").keep_alive, "connection keep-alive is always keep-alive");
1426     }
1427 
1428     #[test]
test_client_request_encode_title_case()1429     fn test_client_request_encode_title_case() {
1430         use http::header::HeaderValue;
1431         use proto::BodyLength;
1432 
1433         let mut head = MessageHead::default();
1434         head.headers.insert("content-length", HeaderValue::from_static("10"));
1435         head.headers.insert("content-type", HeaderValue::from_static("application/json"));
1436         head.headers.insert("*-*", HeaderValue::from_static("o_o"));
1437 
1438         let mut vec = Vec::new();
1439         Client::encode(Encode {
1440             head: &mut head,
1441             body: Some(BodyLength::Known(10)),
1442             keep_alive: true,
1443             req_method: &mut None,
1444             title_case_headers: true,
1445         }, &mut vec).unwrap();
1446 
1447         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());
1448     }
1449 
1450     #[test]
test_server_encode_connect_method()1451     fn test_server_encode_connect_method() {
1452         let mut head = MessageHead::default();
1453 
1454         let mut vec = Vec::new();
1455         let encoder = Server::encode(Encode {
1456             head: &mut head,
1457             body: None,
1458             keep_alive: true,
1459             req_method: &mut Some(Method::CONNECT),
1460             title_case_headers: false,
1461         }, &mut vec).unwrap();
1462 
1463         assert!(encoder.is_last());
1464     }
1465 
1466     #[test]
parse_header_htabs()1467     fn parse_header_htabs() {
1468         let mut bytes = BytesMut::from("HTTP/1.1 200 OK\r\nserver: hello\tworld\r\n\r\n");
1469         let parsed = Client::parse(&mut bytes, ParseContext {
1470             cached_headers: &mut None,
1471             req_method: &mut Some(Method::GET),
1472         })
1473             .expect("parse ok")
1474             .expect("parse complete");
1475 
1476         assert_eq!(parsed.head.headers["server"], "hello\tworld");
1477     }
1478 
1479     #[cfg(feature = "nightly")]
1480     use test::Bencher;
1481 
1482     #[cfg(feature = "nightly")]
1483     #[bench]
bench_parse_incoming(b: &mut Bencher)1484     fn bench_parse_incoming(b: &mut Bencher) {
1485         let mut raw = BytesMut::from(
1486             b"GET /super_long_uri/and_whatever?what_should_we_talk_about/\
1487             I_wonder/Hard_to_write_in_an_uri_after_all/you_have_to_make\
1488             _up_the_punctuation_yourself/how_fun_is_that?test=foo&test1=\
1489             foo1&test2=foo2&test3=foo3&test4=foo4 HTTP/1.1\r\nHost: \
1490             hyper.rs\r\nAccept: a lot of things\r\nAccept-Charset: \
1491             utf8\r\nAccept-Encoding: *\r\nAccess-Control-Allow-\
1492             Credentials: None\r\nAccess-Control-Allow-Origin: None\r\n\
1493             Access-Control-Allow-Methods: None\r\nAccess-Control-Allow-\
1494             Headers: None\r\nContent-Encoding: utf8\r\nContent-Security-\
1495             Policy: None\r\nContent-Type: text/html\r\nOrigin: hyper\
1496             \r\nSec-Websocket-Extensions: It looks super important!\r\n\
1497             Sec-Websocket-Origin: hyper\r\nSec-Websocket-Version: 4.3\r\
1498             \nStrict-Transport-Security: None\r\nUser-Agent: hyper\r\n\
1499             X-Content-Duration: None\r\nX-Content-Security-Policy: None\
1500             \r\nX-DNSPrefetch-Control: None\r\nX-Frame-Options: \
1501             Something important obviously\r\nX-Requested-With: Nothing\
1502             \r\n\r\n".to_vec()
1503         );
1504         let len = raw.len();
1505         let mut headers = Some(HeaderMap::new());
1506 
1507         b.bytes = len as u64;
1508         b.iter(|| {
1509             let mut msg = Server::parse(&mut raw, ParseContext {
1510                 cached_headers: &mut headers,
1511                 req_method: &mut None,
1512             }).unwrap().unwrap();
1513             ::test::black_box(&msg);
1514             msg.head.headers.clear();
1515             headers = Some(msg.head.headers);
1516             restart(&mut raw, len);
1517         });
1518 
1519 
1520         fn restart(b: &mut BytesMut, len: usize) {
1521             b.reserve(1);
1522             unsafe {
1523                 b.set_len(len);
1524             }
1525         }
1526     }
1527 
1528     #[cfg(feature = "nightly")]
1529     #[bench]
bench_parse_short(b: &mut Bencher)1530     fn bench_parse_short(b: &mut Bencher) {
1531         let s = &b"GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"[..];
1532         let mut raw = BytesMut::from(s.to_vec());
1533         let len = raw.len();
1534         let mut headers = Some(HeaderMap::new());
1535 
1536         b.bytes = len as u64;
1537         b.iter(|| {
1538             let mut msg = Server::parse(&mut raw, ParseContext {
1539                 cached_headers: &mut headers,
1540                 req_method: &mut None,
1541             }).unwrap().unwrap();
1542             ::test::black_box(&msg);
1543             msg.head.headers.clear();
1544             headers = Some(msg.head.headers);
1545             restart(&mut raw, len);
1546         });
1547 
1548 
1549         fn restart(b: &mut BytesMut, len: usize) {
1550             b.reserve(1);
1551             unsafe {
1552                 b.set_len(len);
1553             }
1554         }
1555     }
1556 
1557     #[cfg(feature = "nightly")]
1558     #[bench]
bench_server_encode_headers_preset(b: &mut Bencher)1559     fn bench_server_encode_headers_preset(b: &mut Bencher) {
1560         use http::header::HeaderValue;
1561         use proto::BodyLength;
1562 
1563         let len = 108;
1564         b.bytes = len as u64;
1565 
1566         let mut head = MessageHead::default();
1567         let mut headers = HeaderMap::new();
1568         headers.insert("content-length", HeaderValue::from_static("10"));
1569         headers.insert("content-type", HeaderValue::from_static("application/json"));
1570 
1571         b.iter(|| {
1572             let mut vec = Vec::new();
1573             head.headers = headers.clone();
1574             Server::encode(Encode {
1575                 head: &mut head,
1576                 body: Some(BodyLength::Known(10)),
1577                 keep_alive: true,
1578                 req_method: &mut Some(Method::GET),
1579                 title_case_headers: false,
1580             }, &mut vec).unwrap();
1581             assert_eq!(vec.len(), len);
1582             ::test::black_box(vec);
1583         })
1584     }
1585 
1586     #[cfg(feature = "nightly")]
1587     #[bench]
bench_server_encode_no_headers(b: &mut Bencher)1588     fn bench_server_encode_no_headers(b: &mut Bencher) {
1589         use proto::BodyLength;
1590 
1591         let len = 76;
1592         b.bytes = len as u64;
1593 
1594         let mut head = MessageHead::default();
1595         let mut vec = Vec::with_capacity(128);
1596 
1597         b.iter(|| {
1598             Server::encode(Encode {
1599                 head: &mut head,
1600                 body: Some(BodyLength::Known(10)),
1601                 keep_alive: true,
1602                 req_method: &mut Some(Method::GET),
1603                 title_case_headers: false,
1604             }, &mut vec).unwrap();
1605             assert_eq!(vec.len(), len);
1606             ::test::black_box(&vec);
1607 
1608             vec.clear();
1609         })
1610     }
1611 }
1612