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