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