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