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