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