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