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 if let Some(max_header_size) = ctx.h1_max_header_size {
184 if parsed_len > max_header_size {
185 return Err(Parse::TooLarge);
186 }
187 }
188 len = parsed_len;
189 let uri = req.path.expect("httparse completed");
190 if uri.len() > MAX_URI_LEN {
191 return Err(Parse::UriTooLong);
192 }
193 method =
194 Method::from_bytes(req.method.expect("httparse completed").as_bytes())?;
195 path_range = Server::record_path_range(bytes, uri);
196 version = if req.version.expect("httparse completed") == 1 {
197 keep_alive = true;
198 is_http_11 = true;
199 Version::HTTP_11
200 } else {
201 keep_alive = false;
202 is_http_11 = false;
203 Version::HTTP_10
204 };
205
206 record_header_indices(bytes, req.headers, &mut headers_indices)?;
207 headers_len = req.headers.len();
208 }
209 Ok(httparse::Status::Partial) => return Ok(None),
210 Err(httparse::Error::Token) => {
212 return Err({
213 if req.method.is_none() {
214 Parse::Method
215 } else {
216 debug_assert!(req.path.is_none());
217 Parse::Uri
218 }
219 })
220 }
221 Err(err) => return Err(err.into()),
222 }
223 };
224
225 let slice = buf.split_to(len).freeze();
226 let uri = {
227 let uri_bytes = slice.slice_ref(&slice[path_range]);
228 http::Uri::from_maybe_shared(uri_bytes)?
230 };
231 subject = RequestLine(method, uri);
232
233 let mut decoder = DecodedLength::ZERO;
243 let mut expect_continue = false;
244 let mut con_len = None;
245 let mut is_cl = false;
246 let mut is_te = false;
247 let mut is_te_chunked = false;
248 let mut wants_upgrade = subject.0 == Method::CONNECT;
249
250 let mut header_case_map = if ctx.preserve_header_case {
251 Some(HeaderCaseMap::default())
252 } else {
253 None
254 };
255
256 #[cfg(feature = "ffi")]
257 let mut header_order = if ctx.preserve_header_order {
258 Some(OriginalHeaderOrder::default())
259 } else {
260 None
261 };
262
263 let mut headers = ctx.cached_headers.take().unwrap_or_default();
264 let mut saw_connection_close = false;
265
266 headers.reserve(headers_len);
267
268 for header in &headers_indices[..headers_len] {
269 let header = unsafe { header.assume_init_ref() };
271 let name = header_name!(&slice[header.name.0..header.name.1]);
272 let value = header_value!(slice.slice(header.value.0..header.value.1));
273
274 match name {
275 header::TRANSFER_ENCODING => {
276 if !is_http_11 {
281 debug!("HTTP/1.0 cannot have Transfer-Encoding header");
282 return Err(Parse::transfer_encoding_unexpected());
283 }
284 is_te = true;
285 if is_cl && con_len.take().is_some() {
286 headers.remove(header::CONTENT_LENGTH);
287 }
288 if headers::is_chunked_(&value) {
289 is_te_chunked = true;
290 decoder = DecodedLength::CHUNKED;
291 } else {
292 is_te_chunked = false;
293 }
294 }
295 header::CONTENT_LENGTH => {
296 is_cl = true;
297 if is_te {
298 continue;
299 }
300 let len = headers::content_length_parse(&value)
301 .ok_or_else(Parse::content_length_invalid)?;
302 if let Some(prev) = con_len {
303 if prev != len {
304 debug!(
305 "multiple Content-Length headers with different values: [{}, {}]",
306 prev, len,
307 );
308 return Err(Parse::content_length_invalid());
309 }
310 continue;
312 }
313 decoder = DecodedLength::checked_new(len)?;
314 con_len = Some(len);
315 }
316 header::CONNECTION => {
317 if saw_connection_close || headers::connection_close(&value) {
321 saw_connection_close = true;
322 keep_alive = false;
323 } else if !keep_alive {
324 keep_alive = headers::connection_keep_alive(&value);
326 }
327 }
328 header::EXPECT => {
329 expect_continue = value.as_bytes().eq_ignore_ascii_case(b"100-continue");
333 }
334 header::UPGRADE => {
335 wants_upgrade = is_http_11;
337 }
338
339 _ => (),
340 }
341
342 if let Some(header_case_map) = &mut header_case_map {
343 header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
344 }
345
346 #[cfg(feature = "ffi")]
347 if let Some(header_order) = &mut header_order {
348 header_order.append(&name);
349 }
350
351 headers.append(name, value);
352 }
353
354 if is_te && !is_te_chunked {
355 debug!("request with transfer-encoding header, but not chunked, bad request");
356 return Err(Parse::transfer_encoding_invalid());
357 }
358
359 if is_te && is_cl {
360 keep_alive = false;
361 }
362
363 let mut extensions = http::Extensions::default();
364
365 if let Some(header_case_map) = header_case_map {
366 extensions.insert(header_case_map);
367 }
368
369 #[cfg(feature = "ffi")]
370 if let Some(header_order) = header_order {
371 extensions.insert(header_order);
372 }
373
374 *ctx.req_method = Some(subject.0.clone());
375
376 Ok(Some(ParsedMessage {
377 head: MessageHead {
378 version,
379 subject,
380 headers,
381 extensions,
382 },
383 decode: decoder,
384 expect_continue,
385 keep_alive,
386 wants_upgrade,
387 }))
388 }
389
390 fn encode(mut msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder> {
391 trace!(
392 "Server::encode status={:?}, body={:?}, req_method={:?}",
393 msg.head.subject,
394 msg.body,
395 msg.req_method
396 );
397
398 let mut wrote_len = false;
399
400 let (ret, is_last) = if msg.head.subject == StatusCode::SWITCHING_PROTOCOLS {
405 (Ok(()), true)
406 } else if msg.req_method == &Some(Method::CONNECT) && msg.head.subject.is_success() {
407 wrote_len = true;
410 (Ok(()), true)
411 } else if msg.head.subject.is_informational() {
412 warn!("response with 1xx status code not supported");
413 *msg.head = MessageHead::default();
414 msg.head.subject = StatusCode::INTERNAL_SERVER_ERROR;
415 msg.body = None;
416 (Err(crate::Error::new_user_unsupported_status_code()), true)
417 } else {
418 (Ok(()), !msg.keep_alive)
419 };
420
421 let orig_len = dst.len();
425
426 let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
427 dst.reserve(init_cap);
428
429 let custom_reason_phrase = msg.head.extensions.get::<crate::ext::ReasonPhrase>();
430
431 if msg.head.version == Version::HTTP_11
432 && msg.head.subject == StatusCode::OK
433 && custom_reason_phrase.is_none()
434 {
435 extend(dst, b"HTTP/1.1 200 OK\r\n");
436 } else {
437 match msg.head.version {
438 Version::HTTP_10 => extend(dst, b"HTTP/1.0 "),
439 Version::HTTP_11 => extend(dst, b"HTTP/1.1 "),
440 Version::HTTP_2 => {
441 debug!("response with HTTP2 version coerced to HTTP/1.1");
442 extend(dst, b"HTTP/1.1 ");
443 }
444 #[allow(clippy::panic)]
445 other => panic!("unexpected response version: {other:?}"),
446 }
447
448 extend(dst, msg.head.subject.as_str().as_bytes());
449 extend(dst, b" ");
450
451 if let Some(reason) = custom_reason_phrase {
452 extend(dst, reason.as_bytes());
453 } else {
454 extend(
456 dst,
457 msg.head
458 .subject
459 .canonical_reason()
460 .unwrap_or("<none>")
461 .as_bytes(),
462 );
463 }
464
465 extend(dst, b"\r\n");
466 }
467
468 let orig_headers;
469 let extensions = std::mem::take(&mut msg.head.extensions);
470 let orig_headers = match extensions.get::<HeaderCaseMap>() {
471 None if msg.title_case_headers => {
472 orig_headers = HeaderCaseMap::default();
473 Some(&orig_headers)
474 }
475 orig_headers => orig_headers,
476 };
477 let encoder = if let Some(orig_headers) = orig_headers {
478 Self::encode_headers_with_original_case(
479 msg,
480 dst,
481 is_last,
482 orig_len,
483 wrote_len,
484 orig_headers,
485 )?
486 } else {
487 Self::encode_headers_with_lower_case(msg, dst, is_last, orig_len, wrote_len)?
488 };
489
490 ret.map(|()| encoder)
491 }
492
493 fn on_error(err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
494 use crate::error::Kind;
495 let status = match *err.kind() {
496 Kind::Parse(Parse::Method)
497 | Kind::Parse(Parse::Header(_))
498 | Kind::Parse(Parse::Uri)
499 | Kind::Parse(Parse::Version) => StatusCode::BAD_REQUEST,
500 Kind::Parse(Parse::TooLarge) => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE,
501 Kind::Parse(Parse::UriTooLong) => StatusCode::URI_TOO_LONG,
502 _ => return None,
503 };
504
505 debug!("sending automatic response ({}) for parse error", status);
506 let msg = MessageHead {
507 subject: status,
508 ..Default::default()
509 };
510 Some(msg)
511 }
512
513 fn is_server() -> bool {
514 true
515 }
516
517 fn update_date() {
518 date::update();
519 }
520}
521
522#[cfg(feature = "server")]
523impl Server {
524 fn can_have_body(method: Option<&Method>, status: StatusCode) -> bool {
525 Server::can_chunked(method, status)
526 }
527
528 fn can_chunked(method: Option<&Method>, status: StatusCode) -> bool {
529 if method == Some(&Method::HEAD)
530 || method == Some(&Method::CONNECT) && status.is_success()
531 || status.is_informational()
532 {
533 false
534 } else {
535 !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED)
536 }
537 }
538
539 fn can_have_content_length(method: Option<&Method>, status: StatusCode) -> bool {
540 if status.is_informational() || method == Some(&Method::CONNECT) && status.is_success() {
541 false
542 } else {
543 !matches!(status, StatusCode::NO_CONTENT | StatusCode::NOT_MODIFIED)
544 }
545 }
546
547 fn can_have_implicit_zero_content_length(method: Option<&Method>, status: StatusCode) -> bool {
548 Server::can_have_content_length(method, status) && method != Some(&Method::HEAD)
549 }
550
551 fn encode_headers_with_lower_case(
552 msg: Encode<'_, StatusCode>,
553 dst: &mut Vec<u8>,
554 is_last: bool,
555 orig_len: usize,
556 wrote_len: bool,
557 ) -> crate::Result<Encoder> {
558 struct LowercaseWriter;
559
560 impl HeaderNameWriter for LowercaseWriter {
561 #[inline]
562 fn write_full_header_line(
563 &mut self,
564 dst: &mut Vec<u8>,
565 line: &str,
566 _: (HeaderName, &str),
567 ) {
568 extend(dst, line.as_bytes());
569 }
570
571 #[inline]
572 fn write_header_name_with_colon(
573 &mut self,
574 dst: &mut Vec<u8>,
575 name_with_colon: &str,
576 _: HeaderName,
577 ) {
578 extend(dst, name_with_colon.as_bytes());
579 }
580
581 #[inline]
582 fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName) {
583 extend(dst, name.as_str().as_bytes());
584 }
585 }
586
587 Self::encode_headers(msg, dst, is_last, orig_len, wrote_len, LowercaseWriter)
588 }
589
590 #[cold]
591 #[inline(never)]
592 fn encode_headers_with_original_case(
593 msg: Encode<'_, StatusCode>,
594 dst: &mut Vec<u8>,
595 is_last: bool,
596 orig_len: usize,
597 wrote_len: bool,
598 orig_headers: &HeaderCaseMap,
599 ) -> crate::Result<Encoder> {
600 struct OrigCaseWriter<'map> {
601 map: &'map HeaderCaseMap,
602 current: Option<(HeaderName, ValueIter<'map, Bytes>)>,
603 title_case_headers: bool,
604 }
605
606 impl HeaderNameWriter for OrigCaseWriter<'_> {
607 #[inline]
608 fn write_full_header_line(
609 &mut self,
610 dst: &mut Vec<u8>,
611 _: &str,
612 (name, rest): (HeaderName, &str),
613 ) {
614 self.write_header_name(dst, &name);
615 extend(dst, rest.as_bytes());
616 }
617
618 #[inline]
619 fn write_header_name_with_colon(
620 &mut self,
621 dst: &mut Vec<u8>,
622 _: &str,
623 name: HeaderName,
624 ) {
625 self.write_header_name(dst, &name);
626 extend(dst, b": ");
627 }
628
629 #[inline]
630 fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName) {
631 let Self {
632 map,
633 current,
634 title_case_headers,
635 } = self;
636 if current.as_ref().map_or(true, |(last, _)| last != name) {
637 *current = None;
638 }
639 let (_, values) =
640 current.get_or_insert_with(|| (name.clone(), map.get_all_internal(name)));
641
642 if let Some(orig_name) = values.next() {
643 extend(dst, orig_name);
644 } else if *title_case_headers {
645 title_case(dst, name.as_str().as_bytes());
646 } else {
647 extend(dst, name.as_str().as_bytes());
648 }
649 }
650 }
651
652 let header_name_writer = OrigCaseWriter {
653 map: orig_headers,
654 current: None,
655 title_case_headers: msg.title_case_headers,
656 };
657
658 Self::encode_headers(msg, dst, is_last, orig_len, wrote_len, header_name_writer)
659 }
660
661 #[inline]
662 fn encode_headers<W>(
663 msg: Encode<'_, StatusCode>,
664 dst: &mut Vec<u8>,
665 mut is_last: bool,
666 orig_len: usize,
667 mut wrote_len: bool,
668 mut header_name_writer: W,
669 ) -> crate::Result<Encoder>
670 where
671 W: HeaderNameWriter,
672 {
673 let rewind = |dst: &mut Vec<u8>| {
677 dst.truncate(orig_len);
678 };
679
680 let mut encoder = Encoder::length(0);
681 let mut allowed_trailer_fields: Option<Vec<HeaderName>> = None;
682 let mut wrote_date = false;
683 let mut cur_name = None;
684 let mut is_name_written = false;
685 let mut must_write_chunked = false;
686 let mut prev_con_len = None;
687
688 macro_rules! handle_is_name_written {
689 () => {{
690 if is_name_written {
691 debug_assert_ne!(
693 &dst[dst.len() - 2..],
694 b"\r\n",
695 "previous header wrote newline but set is_name_written"
696 );
697
698 if must_write_chunked {
699 extend(dst, b", chunked\r\n");
700 } else {
701 extend(dst, b"\r\n");
702 }
703 }
704 }};
705 }
706
707 'headers: for (opt_name, value) in msg.head.headers.drain() {
708 if let Some(n) = opt_name {
709 cur_name = Some(n);
710 handle_is_name_written!();
711 is_name_written = false;
712 }
713 let name = cur_name.as_ref().expect("current header name");
714 match *name {
715 header::CONTENT_LENGTH => {
716 if wrote_len && !is_name_written {
717 warn!("unexpected content-length found, canceling");
718 rewind(dst);
719 return Err(crate::Error::new_user_header());
720 }
721 match msg.body {
722 Some(BodyLength::Known(known_len)) => {
723 #[cfg(debug_assertions)]
731 {
732 if let Some(len) = headers::content_length_parse(&value) {
733 if msg.req_method != &Some(Method::HEAD) || known_len != 0 {
734 assert!(
735 len == known_len,
736 "payload claims content-length of {known_len}, custom content-length header claims {len}",
737 );
738 }
739 }
740 }
741
742 if !is_name_written {
743 encoder = Encoder::length(known_len);
744 header_name_writer.write_header_name_with_colon(
745 dst,
746 "content-length: ",
747 header::CONTENT_LENGTH,
748 );
749 extend(dst, value.as_bytes());
750 wrote_len = true;
751 is_name_written = true;
752 }
753 continue 'headers;
754 }
755 Some(BodyLength::Unknown) => {
756 if let Some(len) = headers::content_length_parse(&value) {
762 if let Some(prev) = prev_con_len {
763 if prev != len {
764 warn!(
765 "multiple Content-Length values found: [{}, {}]",
766 prev, len
767 );
768 rewind(dst);
769 return Err(crate::Error::new_user_header());
770 }
771 debug_assert!(is_name_written);
772 continue 'headers;
773 } else {
774 encoder = Encoder::length(len);
776 header_name_writer.write_header_name_with_colon(
777 dst,
778 "content-length: ",
779 header::CONTENT_LENGTH,
780 );
781 extend(dst, value.as_bytes());
782 wrote_len = true;
783 is_name_written = true;
784 prev_con_len = Some(len);
785 continue 'headers;
786 }
787 } else {
788 warn!("illegal Content-Length value: {:?}", value);
789 rewind(dst);
790 return Err(crate::Error::new_user_header());
791 }
792 }
793 None => {
794 if msg.req_method == &Some(Method::HEAD) {
801 debug_assert_eq!(encoder, Encoder::length(0));
802 } else {
803 if value.as_bytes() != b"0" {
804 warn!(
805 "content-length value found, but empty body provided: {:?}",
806 value
807 );
808 }
809 continue 'headers;
810 }
811 }
812 }
813 wrote_len = true;
814 }
815 header::TRANSFER_ENCODING => {
816 if wrote_len && !is_name_written {
817 warn!("unexpected transfer-encoding found, canceling");
818 rewind(dst);
819 return Err(crate::Error::new_user_header());
820 }
821 if msg.head.version == Version::HTTP_10
823 || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
824 {
825 continue;
826 }
827 wrote_len = true;
828 must_write_chunked = !headers::is_chunked_(&value);
831
832 if !is_name_written {
833 encoder = Encoder::chunked();
834 is_name_written = true;
835 header_name_writer.write_header_name_with_colon(
836 dst,
837 "transfer-encoding: ",
838 header::TRANSFER_ENCODING,
839 );
840 extend(dst, value.as_bytes());
841 } else {
842 extend(dst, b", ");
843 extend(dst, value.as_bytes());
844 }
845 continue 'headers;
846 }
847 header::CONNECTION => {
848 if !is_last && headers::connection_close(&value) {
849 is_last = true;
850 }
851 if !is_name_written {
852 is_name_written = true;
853 header_name_writer.write_header_name_with_colon(
854 dst,
855 "connection: ",
856 header::CONNECTION,
857 );
858 extend(dst, value.as_bytes());
859 } else {
860 extend(dst, b", ");
861 extend(dst, value.as_bytes());
862 }
863 continue 'headers;
864 }
865 header::DATE => {
866 wrote_date = true;
867 }
868 header::TRAILER => {
869 if msg.head.version == Version::HTTP_10
871 || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
872 {
873 continue;
874 }
875
876 if !is_name_written {
877 is_name_written = true;
878 header_name_writer.write_header_name_with_colon(
879 dst,
880 "trailer: ",
881 header::TRAILER,
882 );
883 extend(dst, value.as_bytes());
884 } else {
885 extend(dst, b", ");
886 extend(dst, value.as_bytes());
887 }
888
889 if let Ok(value_str) = value.to_str() {
893 let names: Vec<HeaderName> = value_str
894 .split(',')
895 .filter_map(|s| HeaderName::from_bytes(s.trim().as_bytes()).ok())
896 .collect();
897
898 match &mut allowed_trailer_fields {
899 Some(fields) => {
900 fields.extend(names);
901 }
902 None => {
903 allowed_trailer_fields = Some(names);
904 }
905 }
906 }
907
908 continue 'headers;
909 }
910 _ => (),
911 }
912 debug_assert!(
917 !is_name_written,
918 "{name:?} set is_name_written and didn't continue loop",
919 );
920 header_name_writer.write_header_name(dst, name);
921 extend(dst, b": ");
922 extend(dst, value.as_bytes());
923 extend(dst, b"\r\n");
924 }
925
926 handle_is_name_written!();
927
928 if !wrote_len {
929 encoder = match msg.body {
930 Some(BodyLength::Unknown) => {
931 if msg.head.version == Version::HTTP_10
932 || !Server::can_chunked(msg.req_method.as_ref(), msg.head.subject)
933 {
934 Encoder::close_delimited()
935 } else {
936 header_name_writer.write_full_header_line(
937 dst,
938 "transfer-encoding: chunked\r\n",
939 (header::TRANSFER_ENCODING, ": chunked\r\n"),
940 );
941 Encoder::chunked()
942 }
943 }
944 None | Some(BodyLength::Known(0)) => {
945 if Server::can_have_implicit_zero_content_length(
946 msg.req_method.as_ref(),
947 msg.head.subject,
948 ) {
949 header_name_writer.write_full_header_line(
950 dst,
951 "content-length: 0\r\n",
952 (header::CONTENT_LENGTH, ": 0\r\n"),
953 );
954 }
955 Encoder::length(0)
956 }
957 Some(BodyLength::Known(len)) => {
958 if !Server::can_have_content_length(msg.req_method.as_ref(), msg.head.subject) {
959 Encoder::length(0)
960 } else {
961 header_name_writer.write_header_name_with_colon(
962 dst,
963 "content-length: ",
964 header::CONTENT_LENGTH,
965 );
966 extend(dst, ::itoa::Buffer::new().format(len).as_bytes());
967 extend(dst, b"\r\n");
968 Encoder::length(len)
969 }
970 }
971 };
972 }
973
974 if !Server::can_have_body(msg.req_method.as_ref(), msg.head.subject) {
975 trace!(
976 "server body forced to 0; method={:?}, status={:?}",
977 msg.req_method,
978 msg.head.subject
979 );
980 encoder = Encoder::length(0);
981 }
982
983 if !wrote_date && msg.date_header {
986 dst.reserve(date::DATE_VALUE_LENGTH + 8);
987 header_name_writer.write_header_name_with_colon(dst, "date: ", header::DATE);
988 date::extend(dst);
989 extend(dst, b"\r\n\r\n");
990 } else {
991 extend(dst, b"\r\n");
992 }
993
994 if encoder.is_chunked() {
995 if let Some(allowed_trailer_fields) = allowed_trailer_fields {
996 encoder = encoder.into_chunked_with_trailing_fields(allowed_trailer_fields);
997 }
998 }
999
1000 Ok(encoder.set_last(is_last))
1001 }
1002
1003 #[inline]
1005 fn record_path_range(bytes: &[u8], req_path: &str) -> std::ops::Range<usize> {
1006 let bytes_ptr = bytes.as_ptr() as usize;
1007 let start = req_path.as_ptr() as usize - bytes_ptr;
1008 let end = start + req_path.len();
1009 std::ops::Range { start, end }
1010 }
1011}
1012
1013#[cfg(feature = "server")]
1014trait HeaderNameWriter {
1015 fn write_full_header_line(
1016 &mut self,
1017 dst: &mut Vec<u8>,
1018 line: &str,
1019 name_value_pair: (HeaderName, &str),
1020 );
1021 fn write_header_name_with_colon(
1022 &mut self,
1023 dst: &mut Vec<u8>,
1024 name_with_colon: &str,
1025 name: HeaderName,
1026 );
1027 fn write_header_name(&mut self, dst: &mut Vec<u8>, name: &HeaderName);
1028}
1029
1030#[cfg(feature = "client")]
1031impl Http1Transaction for Client {
1032 type Incoming = StatusCode;
1033 type Outgoing = RequestLine;
1034 #[cfg(feature = "tracing")]
1035 const LOG: &'static str = "{role=client}";
1036
1037 fn parse(buf: &mut BytesMut, ctx: ParseContext<'_>) -> ParseResult<StatusCode> {
1038 debug_assert!(!buf.is_empty(), "parse called with empty buf");
1039
1040 loop {
1042 let mut headers_indices: SmallVec<[MaybeUninit<HeaderIndices>; DEFAULT_MAX_HEADERS]> =
1043 match ctx.h1_max_headers {
1044 Some(cap) => smallvec![MaybeUninit::uninit(); cap],
1045 None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
1046 };
1047 let (len, status, reason, version, headers_len) = {
1048 let mut headers: SmallVec<
1049 [MaybeUninit<httparse::Header<'_>>; DEFAULT_MAX_HEADERS],
1050 > = match ctx.h1_max_headers {
1051 Some(cap) => smallvec![MaybeUninit::uninit(); cap],
1052 None => smallvec_inline![MaybeUninit::uninit(); DEFAULT_MAX_HEADERS],
1053 };
1054 trace!(bytes = buf.len(), "Response.parse");
1055 let mut res = httparse::Response::new(&mut []);
1056 let bytes = buf.as_ref();
1057 match ctx.h1_parser_config.parse_response_with_uninit_headers(
1058 &mut res,
1059 bytes,
1060 &mut headers,
1061 ) {
1062 Ok(httparse::Status::Complete(len)) => {
1063 trace!("Response.parse Complete({})", len);
1064 if let Some(max_header_size) = ctx.h1_max_header_size {
1065 if len > max_header_size {
1066 return Err(Parse::TooLarge);
1067 }
1068 }
1069 let status = StatusCode::from_u16(res.code.expect("httparse completed"))?;
1070
1071 let reason = {
1072 let reason = res.reason.expect("httparse completed");
1073 if Some(reason) != status.canonical_reason() {
1075 Some(Bytes::copy_from_slice(reason.as_bytes()))
1076 } else {
1077 None
1078 }
1079 };
1080
1081 let version = if res.version.expect("httparse completed") == 1 {
1082 Version::HTTP_11
1083 } else {
1084 Version::HTTP_10
1085 };
1086 record_header_indices(bytes, res.headers, &mut headers_indices)?;
1087 let headers_len = res.headers.len();
1088 (len, status, reason, version, headers_len)
1089 }
1090 Ok(httparse::Status::Partial) => return Ok(None),
1091 Err(httparse::Error::Version) if ctx.h09_responses => {
1092 trace!("Response.parse accepted HTTP/0.9 response");
1093
1094 (0, StatusCode::OK, None, Version::HTTP_09, 0)
1095 }
1096 Err(e) => return Err(e.into()),
1097 }
1098 };
1099
1100 let mut slice = buf.split_to(len);
1101
1102 if ctx
1103 .h1_parser_config
1104 .obsolete_multiline_headers_in_responses_are_allowed()
1105 {
1106 for header in &mut headers_indices[..headers_len] {
1107 let header = unsafe { header.assume_init_mut() };
1109 Client::obs_fold_line(&mut slice, header);
1110 }
1111 }
1112
1113 let slice = slice.freeze();
1114
1115 let mut headers = ctx.cached_headers.take().unwrap_or_default();
1116
1117 let mut keep_alive = version == Version::HTTP_11;
1118 let mut saw_connection_close = false;
1119
1120 let mut header_case_map = if ctx.preserve_header_case {
1121 Some(HeaderCaseMap::default())
1122 } else {
1123 None
1124 };
1125
1126 #[cfg(feature = "ffi")]
1127 let mut header_order = if ctx.preserve_header_order {
1128 Some(OriginalHeaderOrder::default())
1129 } else {
1130 None
1131 };
1132
1133 headers.reserve(headers_len);
1134 for header in &headers_indices[..headers_len] {
1135 let header = unsafe { header.assume_init_ref() };
1137 let name = header_name!(&slice[header.name.0..header.name.1]);
1138 let value = header_value!(slice.slice(header.value.0..header.value.1));
1139
1140 if let header::CONNECTION = name {
1141 if saw_connection_close || headers::connection_close(&value) {
1145 saw_connection_close = true;
1146 keep_alive = false;
1147 } else if !keep_alive {
1148 keep_alive = headers::connection_keep_alive(&value);
1150 }
1151 }
1152
1153 if let Some(header_case_map) = &mut header_case_map {
1154 header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
1155 }
1156
1157 #[cfg(feature = "ffi")]
1158 if let Some(header_order) = &mut header_order {
1159 header_order.append(&name);
1160 }
1161
1162 headers.append(name, value);
1163 }
1164
1165 let mut extensions = http::Extensions::default();
1166
1167 if let Some(header_case_map) = header_case_map {
1168 extensions.insert(header_case_map);
1169 }
1170
1171 #[cfg(feature = "ffi")]
1172 if let Some(header_order) = header_order {
1173 extensions.insert(header_order);
1174 }
1175
1176 if let Some(reason) = reason {
1177 let reason = crate::ext::ReasonPhrase::from_bytes_unchecked(reason);
1180 extensions.insert(reason);
1181 }
1182
1183 let head = MessageHead {
1184 version,
1185 subject: status,
1186 headers,
1187 extensions,
1188 };
1189 if let Some((decode, is_upgrade)) = Client::decoder(&head, ctx.req_method)? {
1190 return Ok(Some(ParsedMessage {
1191 head,
1192 decode,
1193 expect_continue: false,
1194 keep_alive: keep_alive && !is_upgrade,
1197 wants_upgrade: is_upgrade,
1198 }));
1199 }
1200
1201 if head.subject.is_informational() {
1202 if let Some(callback) = ctx.on_informational {
1203 callback.call(head.into_response(()));
1204 }
1205 }
1206
1207 if buf.is_empty() {
1210 return Ok(None);
1211 }
1212 }
1213 }
1214
1215 fn encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec<u8>) -> crate::Result<Encoder> {
1216 trace!(
1217 "Client::encode method={:?}, body={:?}",
1218 msg.head.subject.0,
1219 msg.body
1220 );
1221
1222 *msg.req_method = Some(msg.head.subject.0.clone());
1223
1224 let body = Client::set_length(msg.head, msg.body);
1225
1226 let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE;
1227 dst.reserve(init_cap);
1228
1229 extend(dst, msg.head.subject.0.as_str().as_bytes());
1230 extend(dst, b" ");
1231 let _ = write!(FastWrite(dst), "{} ", msg.head.subject.1);
1233
1234 match msg.head.version {
1235 Version::HTTP_10 => extend(dst, b"HTTP/1.0"),
1236 Version::HTTP_11 => extend(dst, b"HTTP/1.1"),
1237 Version::HTTP_2 => {
1238 debug!("request with HTTP2 version coerced to HTTP/1.1");
1239 extend(dst, b"HTTP/1.1");
1240 }
1241 #[allow(clippy::panic)]
1242 other => panic!("unexpected request version: {other:?}"),
1243 }
1244 extend(dst, b"\r\n");
1245
1246 if let Some(orig_headers) = msg.head.extensions.get::<HeaderCaseMap>() {
1247 write_headers_original_case(
1248 &msg.head.headers,
1249 orig_headers,
1250 dst,
1251 msg.title_case_headers,
1252 );
1253 } else if msg.title_case_headers {
1254 write_headers_title_case(&msg.head.headers, dst);
1255 } else {
1256 write_headers(&msg.head.headers, dst);
1257 }
1258
1259 extend(dst, b"\r\n");
1260 msg.head.headers.clear(); Ok(body)
1263 }
1264
1265 fn on_error(_err: &crate::Error) -> Option<MessageHead<Self::Outgoing>> {
1266 None
1268 }
1269
1270 fn is_client() -> bool {
1271 true
1272 }
1273}
1274
1275#[cfg(feature = "client")]
1276impl Client {
1277 fn decoder(
1281 inc: &MessageHead<StatusCode>,
1282 method: &mut Option<Method>,
1283 ) -> Result<Option<(DecodedLength, bool)>, Parse> {
1284 match inc.subject.as_u16() {
1294 101 => {
1295 return Ok(Some((DecodedLength::ZERO, true)));
1296 }
1297 100 | 102..=199 => {
1298 trace!("ignoring informational response: {}", inc.subject.as_u16());
1299 return Ok(None);
1300 }
1301 204 | 304 => return Ok(Some((DecodedLength::ZERO, false))),
1302 _ => (),
1303 }
1304 match *method {
1305 Some(Method::HEAD) => {
1306 return Ok(Some((DecodedLength::ZERO, false)));
1307 }
1308 Some(Method::CONNECT) => {
1309 if let 200..=299 = inc.subject.as_u16() {
1310 return Ok(Some((DecodedLength::ZERO, true)));
1311 }
1312 }
1313 Some(_) => {}
1314 None => {
1315 trace!("Client::decoder is missing the Method");
1316 }
1317 }
1318
1319 if inc.headers.contains_key(header::TRANSFER_ENCODING) {
1320 if inc.version == Version::HTTP_10 {
1325 debug!("HTTP/1.0 cannot have Transfer-Encoding header");
1326 Err(Parse::transfer_encoding_unexpected())
1327 } else if headers::transfer_encoding_is_chunked(&inc.headers) {
1328 Ok(Some((DecodedLength::CHUNKED, false)))
1329 } else {
1330 trace!("not chunked, read till eof");
1331 Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1332 }
1333 } else if let Some(len) = headers::content_length_parse_all(&inc.headers) {
1334 Ok(Some((DecodedLength::checked_new(len)?, false)))
1335 } else if inc.headers.contains_key(header::CONTENT_LENGTH) {
1336 debug!("illegal Content-Length header");
1337 Err(Parse::content_length_invalid())
1338 } else {
1339 trace!("neither Transfer-Encoding nor Content-Length");
1340 Ok(Some((DecodedLength::CLOSE_DELIMITED, false)))
1341 }
1342 }
1343 fn set_length(head: &mut RequestHead, body: Option<BodyLength>) -> Encoder {
1344 let body = if let Some(body) = body {
1345 body
1346 } else {
1347 head.headers.remove(header::TRANSFER_ENCODING);
1348 return Encoder::length(0);
1349 };
1350
1351 let can_chunked = head.version == Version::HTTP_11;
1353 let headers = &mut head.headers;
1354
1355 let existing_con_len = headers::content_length_parse_all(headers);
1363 let mut should_remove_con_len = false;
1364
1365 if !can_chunked {
1366 if headers.remove(header::TRANSFER_ENCODING).is_some() {
1368 trace!("removing illegal transfer-encoding header");
1369 }
1370
1371 return if let Some(len) = existing_con_len {
1372 Encoder::length(len)
1373 } else if let BodyLength::Known(len) = body {
1374 set_content_length(headers, len)
1375 } else {
1376 Encoder::length(0)
1379 };
1380 }
1381
1382 let encoder = match headers.entry(header::TRANSFER_ENCODING) {
1385 Entry::Occupied(te) => {
1386 should_remove_con_len = true;
1387 if headers::is_chunked(te.iter()) {
1388 Some(Encoder::chunked())
1389 } else {
1390 warn!("user provided transfer-encoding does not end in 'chunked'");
1391
1392 headers::add_chunked(te);
1409 Some(Encoder::chunked())
1410 }
1411 }
1412 Entry::Vacant(te) => {
1413 if let Some(len) = existing_con_len {
1414 Some(Encoder::length(len))
1415 } else if let BodyLength::Unknown = body {
1416 match head.subject.0 {
1422 Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)),
1423 _ => {
1424 te.insert(HeaderValue::from_static("chunked"));
1425 should_remove_con_len = true;
1428 Some(Encoder::chunked())
1429 }
1430 }
1431 } else {
1432 None
1433 }
1434 }
1435 };
1436
1437 let encoder = encoder.map(|enc| {
1438 if enc.is_chunked() {
1439 let allowed_trailer_fields: Vec<HeaderName> = headers
1443 .get_all(header::TRAILER)
1444 .iter()
1445 .filter_map(|hv| hv.to_str().ok())
1446 .flat_map(|s| s.split(','))
1447 .filter_map(|s| HeaderName::from_bytes(s.trim().as_bytes()).ok())
1448 .collect();
1449
1450 if !allowed_trailer_fields.is_empty() {
1451 return enc.into_chunked_with_trailing_fields(allowed_trailer_fields);
1452 }
1453 }
1454
1455 enc
1456 });
1457
1458 if let Some(encoder) = encoder {
1461 if should_remove_con_len {
1462 headers.remove(header::CONTENT_LENGTH);
1463 }
1464 return encoder;
1465 }
1466
1467 let len = if let BodyLength::Known(len) = body {
1471 len
1472 } else {
1473 unreachable!("BodyLength::Unknown would set chunked");
1474 };
1475
1476 set_content_length(headers, len)
1477 }
1478
1479 fn obs_fold_line(all: &mut [u8], idx: &mut HeaderIndices) {
1480 let buf = &mut all[idx.value.0..idx.value.1];
1493
1494 let first_nl = match buf.iter().position(|b| *b == b'\n') {
1496 Some(i) => i,
1497 None => return,
1498 };
1499
1500 fn trim_start(mut s: &[u8]) -> &[u8] {
1502 while let [first, rest @ ..] = s {
1503 if first.is_ascii_whitespace() {
1504 s = rest;
1505 } else {
1506 break;
1507 }
1508 }
1509 s
1510 }
1511
1512 fn trim_end(mut s: &[u8]) -> &[u8] {
1513 while let [rest @ .., last] = s {
1514 if last.is_ascii_whitespace() {
1515 s = rest;
1516 } else {
1517 break;
1518 }
1519 }
1520 s
1521 }
1522
1523 fn trim(s: &[u8]) -> &[u8] {
1524 trim_start(trim_end(s))
1525 }
1526
1527 let mut unfolded = trim_end(&buf[..first_nl]).to_vec();
1530 for line in buf[first_nl + 1..].split(|b| *b == b'\n') {
1531 unfolded.push(b' ');
1532 unfolded.extend_from_slice(trim(line));
1533 }
1534 buf[..unfolded.len()].copy_from_slice(&unfolded);
1535 idx.value.1 = idx.value.0 + unfolded.len();
1536 }
1537}
1538
1539#[cfg(feature = "client")]
1540fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
1541 if cfg!(debug_assertions) {
1549 match headers.entry(header::CONTENT_LENGTH) {
1550 Entry::Occupied(mut cl) => {
1551 debug_assert!(headers::content_length_parse_all_values(cl.iter()).is_none());
1554 error!("user provided content-length header was invalid");
1558
1559 cl.insert(HeaderValue::from(len));
1560 Encoder::length(len)
1561 }
1562 Entry::Vacant(cl) => {
1563 cl.insert(HeaderValue::from(len));
1564 Encoder::length(len)
1565 }
1566 }
1567 } else {
1568 headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len));
1569 Encoder::length(len)
1570 }
1571}
1572
1573#[derive(Clone, Copy)]
1574struct HeaderIndices {
1575 name: (usize, usize),
1576 value: (usize, usize),
1577}
1578
1579fn record_header_indices(
1580 bytes: &[u8],
1581 headers: &[httparse::Header<'_>],
1582 indices: &mut [MaybeUninit<HeaderIndices>],
1583) -> Result<(), crate::error::Parse> {
1584 let bytes_ptr = bytes.as_ptr() as usize;
1585
1586 for (header, indices) in headers.iter().zip(indices.iter_mut()) {
1587 if header.name.len() >= (1 << 16) {
1588 debug!("header name larger than 64kb: {:?}", header.name);
1589 return Err(crate::error::Parse::TooLarge);
1590 }
1591 let name_start = header.name.as_ptr() as usize - bytes_ptr;
1592 let name_end = name_start + header.name.len();
1593 let value_start = header.value.as_ptr() as usize - bytes_ptr;
1594 let value_end = value_start + header.value.len();
1595
1596 indices.write(HeaderIndices {
1597 name: (name_start, name_end),
1598 value: (value_start, value_end),
1599 });
1600 }
1601
1602 Ok(())
1603}
1604
1605fn title_case(dst: &mut Vec<u8>, name: &[u8]) {
1607 dst.reserve(name.len());
1608
1609 let mut prev = b'-';
1611 for &(mut c) in name {
1612 if prev == b'-' {
1613 c.make_ascii_uppercase();
1614 }
1615 dst.push(c);
1616 prev = c;
1617 }
1618}
1619
1620pub(crate) fn write_headers_title_case(headers: &HeaderMap, dst: &mut Vec<u8>) {
1621 for (name, value) in headers {
1622 title_case(dst, name.as_str().as_bytes());
1623 extend(dst, b": ");
1624 extend(dst, value.as_bytes());
1625 extend(dst, b"\r\n");
1626 }
1627}
1628
1629pub(crate) fn write_headers(headers: &HeaderMap, dst: &mut Vec<u8>) {
1630 for (name, value) in headers {
1631 extend(dst, name.as_str().as_bytes());
1632 extend(dst, b": ");
1633 extend(dst, value.as_bytes());
1634 extend(dst, b"\r\n");
1635 }
1636}
1637
1638#[cold]
1639#[cfg(feature = "client")]
1640fn write_headers_original_case(
1641 headers: &HeaderMap,
1642 orig_case: &HeaderCaseMap,
1643 dst: &mut Vec<u8>,
1644 title_case_headers: bool,
1645) {
1646 for name in headers.keys() {
1652 let mut names = orig_case.get_all(name);
1653
1654 for value in headers.get_all(name) {
1655 if let Some(orig_name) = names.next() {
1656 extend(dst, orig_name.as_ref());
1657 } else if title_case_headers {
1658 title_case(dst, name.as_str().as_bytes());
1659 } else {
1660 extend(dst, name.as_str().as_bytes());
1661 }
1662
1663 if value.is_empty() {
1665 extend(dst, b":\r\n");
1666 } else {
1667 extend(dst, b": ");
1668 extend(dst, value.as_bytes());
1669 extend(dst, b"\r\n");
1670 }
1671 }
1672 }
1673}
1674
1675#[cfg(feature = "client")]
1676struct FastWrite<'data>(&'data mut Vec<u8>);
1677
1678#[cfg(feature = "client")]
1679impl fmt::Write for FastWrite<'_> {
1680 #[inline]
1681 fn write_str(&mut self, s: &str) -> fmt::Result {
1682 extend(self.0, s.as_bytes());
1683 Ok(())
1684 }
1685
1686 #[inline]
1687 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
1688 fmt::write(self, args)
1689 }
1690}
1691
1692#[inline]
1693fn extend(dst: &mut Vec<u8>, data: &[u8]) {
1694 dst.extend_from_slice(data);
1695}
1696
1697#[cfg(test)]
1698mod tests {
1699 use bytes::BytesMut;
1700
1701 use super::*;
1702
1703 #[cfg(feature = "server")]
1704 #[test]
1705 fn test_parse_request() {
1706 let _ = pretty_env_logger::try_init();
1707 let mut raw = BytesMut::from("GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1708 let mut method = None;
1709 let msg = Server::parse(
1710 &mut raw,
1711 ParseContext {
1712 cached_headers: &mut None,
1713 req_method: &mut method,
1714 h1_parser_config: Default::default(),
1715 h1_max_headers: None,
1716 h1_max_header_size: None,
1717 preserve_header_case: false,
1718 #[cfg(feature = "ffi")]
1719 preserve_header_order: false,
1720 h09_responses: false,
1721 #[cfg(feature = "client")]
1722 on_informational: &mut None,
1723 },
1724 )
1725 .unwrap()
1726 .unwrap();
1727 assert_eq!(raw.len(), 0);
1728 assert_eq!(msg.head.subject.0, crate::Method::GET);
1729 assert_eq!(msg.head.subject.1, "/echo");
1730 assert_eq!(msg.head.version, crate::Version::HTTP_11);
1731 assert_eq!(msg.head.headers.len(), 1);
1732 assert_eq!(msg.head.headers["Host"], "hyper.rs");
1733 assert_eq!(method, Some(crate::Method::GET));
1734 }
1735
1736 #[test]
1737 fn test_parse_response() {
1738 let _ = pretty_env_logger::try_init();
1739 let mut raw = BytesMut::from("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1740 let ctx = ParseContext {
1741 cached_headers: &mut None,
1742 req_method: &mut Some(crate::Method::GET),
1743 h1_parser_config: Default::default(),
1744 h1_max_headers: None,
1745 h1_max_header_size: None,
1746 preserve_header_case: false,
1747 #[cfg(feature = "ffi")]
1748 preserve_header_order: false,
1749 h09_responses: false,
1750 #[cfg(feature = "client")]
1751 on_informational: &mut None,
1752 };
1753 let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1754 assert_eq!(raw.len(), 0);
1755 assert_eq!(msg.head.subject, crate::StatusCode::OK);
1756 assert_eq!(msg.head.version, crate::Version::HTTP_11);
1757 assert_eq!(msg.head.headers.len(), 1);
1758 assert_eq!(msg.head.headers["Content-Length"], "0");
1759 }
1760
1761 #[cfg(feature = "server")]
1762 #[test]
1763 fn test_parse_request_errors() {
1764 let mut raw = BytesMut::from("GET htt:p// HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
1765 let ctx = ParseContext {
1766 cached_headers: &mut None,
1767 req_method: &mut None,
1768 h1_parser_config: Default::default(),
1769 h1_max_headers: None,
1770 h1_max_header_size: None,
1771 preserve_header_case: false,
1772 #[cfg(feature = "ffi")]
1773 preserve_header_order: false,
1774 h09_responses: false,
1775 #[cfg(feature = "client")]
1776 on_informational: &mut None,
1777 };
1778 Server::parse(&mut raw, ctx).unwrap_err();
1779 }
1780
1781 const H09_RESPONSE: &str = "Baguettes are super delicious, don't you agree?";
1782
1783 #[test]
1784 fn test_parse_response_h09_allowed() {
1785 let _ = pretty_env_logger::try_init();
1786 let mut raw = BytesMut::from(H09_RESPONSE);
1787 let ctx = ParseContext {
1788 cached_headers: &mut None,
1789 req_method: &mut Some(crate::Method::GET),
1790 h1_parser_config: Default::default(),
1791 h1_max_headers: None,
1792 h1_max_header_size: None,
1793 preserve_header_case: false,
1794 #[cfg(feature = "ffi")]
1795 preserve_header_order: false,
1796 h09_responses: true,
1797 #[cfg(feature = "client")]
1798 on_informational: &mut None,
1799 };
1800 let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1801 assert_eq!(raw, H09_RESPONSE);
1802 assert_eq!(msg.head.subject, crate::StatusCode::OK);
1803 assert_eq!(msg.head.version, crate::Version::HTTP_09);
1804 assert_eq!(msg.head.headers.len(), 0);
1805 }
1806
1807 #[test]
1808 fn test_parse_response_h09_rejected() {
1809 let _ = pretty_env_logger::try_init();
1810 let mut raw = BytesMut::from(H09_RESPONSE);
1811 let ctx = ParseContext {
1812 cached_headers: &mut None,
1813 req_method: &mut Some(crate::Method::GET),
1814 h1_parser_config: Default::default(),
1815 h1_max_headers: None,
1816 h1_max_header_size: None,
1817 preserve_header_case: false,
1818 #[cfg(feature = "ffi")]
1819 preserve_header_order: false,
1820 h09_responses: false,
1821 #[cfg(feature = "client")]
1822 on_informational: &mut None,
1823 };
1824 Client::parse(&mut raw, ctx).unwrap_err();
1825 assert_eq!(raw, H09_RESPONSE);
1826 }
1827
1828 const RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &str =
1829 "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\n\r\n";
1830
1831 #[test]
1832 fn test_parse_allow_response_with_spaces_before_colons() {
1833 use httparse::ParserConfig;
1834
1835 let _ = pretty_env_logger::try_init();
1836 let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1837 let mut h1_parser_config = ParserConfig::default();
1838 h1_parser_config.allow_spaces_after_header_name_in_responses(true);
1839 let ctx = ParseContext {
1840 cached_headers: &mut None,
1841 req_method: &mut Some(crate::Method::GET),
1842 h1_parser_config,
1843 h1_max_headers: None,
1844 h1_max_header_size: None,
1845 preserve_header_case: false,
1846 #[cfg(feature = "ffi")]
1847 preserve_header_order: false,
1848 h09_responses: false,
1849 #[cfg(feature = "client")]
1850 on_informational: &mut None,
1851 };
1852 let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
1853 assert_eq!(raw.len(), 0);
1854 assert_eq!(msg.head.subject, crate::StatusCode::OK);
1855 assert_eq!(msg.head.version, crate::Version::HTTP_11);
1856 assert_eq!(msg.head.headers.len(), 1);
1857 assert_eq!(msg.head.headers["Access-Control-Allow-Credentials"], "true");
1858 }
1859
1860 #[test]
1861 fn test_parse_reject_response_with_spaces_before_colons() {
1862 let _ = pretty_env_logger::try_init();
1863 let mut raw = BytesMut::from(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1864 let ctx = ParseContext {
1865 cached_headers: &mut None,
1866 req_method: &mut Some(crate::Method::GET),
1867 h1_parser_config: Default::default(),
1868 h1_max_headers: None,
1869 h1_max_header_size: 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 Client::parse(&mut raw, ctx).unwrap_err();
1878 }
1879
1880 const REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE: &str =
1881 "GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n";
1882
1883 #[cfg(feature = "server")]
1884 #[test]
1885 fn test_parse_allow_request_with_multiple_spaces_in_request_line() {
1886 use httparse::ParserConfig;
1887
1888 let _ = pretty_env_logger::try_init();
1889 let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1890 let mut h1_parser_config = ParserConfig::default();
1891 h1_parser_config.allow_multiple_spaces_in_request_line_delimiters(true);
1892 let mut method = None;
1893 let ctx = ParseContext {
1894 cached_headers: &mut None,
1895 req_method: &mut method,
1896 h1_parser_config,
1897 h1_max_headers: None,
1898 h1_max_header_size: None,
1899 preserve_header_case: false,
1900 #[cfg(feature = "ffi")]
1901 preserve_header_order: false,
1902 h09_responses: false,
1903 #[cfg(feature = "client")]
1904 on_informational: &mut None,
1905 };
1906 let msg = Server::parse(&mut raw, ctx).unwrap().unwrap();
1907 assert_eq!(raw.len(), 0);
1908 assert_eq!(msg.head.subject.0, crate::Method::GET);
1909 assert_eq!(msg.head.subject.1, "/echo");
1910 assert_eq!(msg.head.version, crate::Version::HTTP_11);
1911 assert_eq!(msg.head.headers.len(), 1);
1912 assert_eq!(msg.head.headers["Host"], "hyper.rs");
1913 assert_eq!(method, Some(crate::Method::GET));
1914 }
1915
1916 #[cfg(feature = "server")]
1917 #[test]
1918 fn test_parse_reject_request_with_multiple_spaces_in_request_line() {
1919 let _ = pretty_env_logger::try_init();
1920 let mut raw = BytesMut::from(REQUEST_WITH_MULTIPLE_SPACES_IN_REQUEST_LINE);
1921 let ctx = ParseContext {
1922 cached_headers: &mut None,
1923 req_method: &mut None,
1924 h1_parser_config: Default::default(),
1925 h1_max_headers: None,
1926 h1_max_header_size: None,
1927 preserve_header_case: false,
1928 #[cfg(feature = "ffi")]
1929 preserve_header_order: false,
1930 h09_responses: false,
1931 #[cfg(feature = "client")]
1932 on_informational: &mut None,
1933 };
1934 Server::parse(&mut raw, ctx).unwrap_err();
1935 }
1936
1937 #[cfg(feature = "server")]
1938 #[test]
1939 fn test_parse_preserve_header_case_in_request() {
1940 let mut raw =
1941 BytesMut::from("GET / HTTP/1.1\r\nHost: hyper.rs\r\nX-BREAD: baguette\r\n\r\n");
1942 let ctx = ParseContext {
1943 cached_headers: &mut None,
1944 req_method: &mut None,
1945 h1_parser_config: Default::default(),
1946 h1_max_headers: None,
1947 h1_max_header_size: None,
1948 preserve_header_case: true,
1949 #[cfg(feature = "ffi")]
1950 preserve_header_order: false,
1951 h09_responses: false,
1952 #[cfg(feature = "client")]
1953 on_informational: &mut None,
1954 };
1955 let parsed_message = Server::parse(&mut raw, ctx).unwrap().unwrap();
1956 let orig_headers = parsed_message
1957 .head
1958 .extensions
1959 .get::<HeaderCaseMap>()
1960 .unwrap();
1961 assert_eq!(
1962 orig_headers
1963 .get_all_internal(&HeaderName::from_static("host"))
1964 .collect::<Vec<_>>(),
1965 vec![&Bytes::from("Host")]
1966 );
1967 assert_eq!(
1968 orig_headers
1969 .get_all_internal(&HeaderName::from_static("x-bread"))
1970 .collect::<Vec<_>>(),
1971 vec![&Bytes::from("X-BREAD")]
1972 );
1973 }
1974
1975 #[cfg(feature = "server")]
1976 #[test]
1977 fn test_decoder_request() {
1978 fn parse(s: &str) -> ParsedMessage<RequestLine> {
1979 let mut bytes = BytesMut::from(s);
1980 Server::parse(
1981 &mut bytes,
1982 ParseContext {
1983 cached_headers: &mut None,
1984 req_method: &mut None,
1985 h1_parser_config: Default::default(),
1986 h1_max_headers: None,
1987 h1_max_header_size: None,
1988 preserve_header_case: false,
1989 #[cfg(feature = "ffi")]
1990 preserve_header_order: false,
1991 h09_responses: false,
1992 #[cfg(feature = "client")]
1993 on_informational: &mut None,
1994 },
1995 )
1996 .expect("parse ok")
1997 .expect("parse complete")
1998 }
1999
2000 fn parse_err(s: &str, comment: &str) -> crate::error::Parse {
2001 let mut bytes = BytesMut::from(s);
2002 Server::parse(
2003 &mut bytes,
2004 ParseContext {
2005 cached_headers: &mut None,
2006 req_method: &mut None,
2007 h1_parser_config: Default::default(),
2008 h1_max_headers: None,
2009 h1_max_header_size: None,
2010 preserve_header_case: false,
2011 #[cfg(feature = "ffi")]
2012 preserve_header_order: false,
2013 h09_responses: false,
2014 #[cfg(feature = "client")]
2015 on_informational: &mut None,
2016 },
2017 )
2018 .expect_err(comment)
2019 }
2020
2021 assert_eq!(
2023 parse(
2024 "\
2025 GET / HTTP/1.1\r\n\
2026 \r\n\
2027 "
2028 )
2029 .decode,
2030 DecodedLength::ZERO
2031 );
2032
2033 assert_eq!(
2034 parse(
2035 "\
2036 POST / HTTP/1.1\r\n\
2037 \r\n\
2038 "
2039 )
2040 .decode,
2041 DecodedLength::ZERO
2042 );
2043
2044 assert_eq!(
2046 parse(
2047 "\
2048 POST / HTTP/1.1\r\n\
2049 transfer-encoding: chunked\r\n\
2050 \r\n\
2051 "
2052 )
2053 .decode,
2054 DecodedLength::CHUNKED
2055 );
2056
2057 assert_eq!(
2058 parse(
2059 "\
2060 POST / HTTP/1.1\r\n\
2061 transfer-encoding: gzip, chunked\r\n\
2062 \r\n\
2063 "
2064 )
2065 .decode,
2066 DecodedLength::CHUNKED
2067 );
2068
2069 assert_eq!(
2070 parse(
2071 "\
2072 POST / HTTP/1.1\r\n\
2073 transfer-encoding: gzip\r\n\
2074 transfer-encoding: chunked\r\n\
2075 \r\n\
2076 "
2077 )
2078 .decode,
2079 DecodedLength::CHUNKED
2080 );
2081
2082 assert_eq!(
2084 parse(
2085 "\
2086 POST / HTTP/1.1\r\n\
2087 content-length: 10\r\n\
2088 \r\n\
2089 "
2090 )
2091 .decode,
2092 DecodedLength::new(10)
2093 );
2094
2095 let msg = parse(
2097 "\
2098 POST / HTTP/1.1\r\n\
2099 content-length: 10\r\n\
2100 transfer-encoding: chunked\r\n\
2101 \r\n\
2102 ",
2103 );
2104 assert_eq!(msg.decode, DecodedLength::CHUNKED);
2105 assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2106 assert!(!msg.keep_alive);
2107
2108 let msg = parse(
2109 "\
2110 POST / HTTP/1.1\r\n\
2111 transfer-encoding: chunked\r\n\
2112 content-length: 10\r\n\
2113 \r\n\
2114 ",
2115 );
2116 assert_eq!(msg.decode, DecodedLength::CHUNKED);
2117 assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2118 assert!(!msg.keep_alive);
2119
2120 let msg = parse(
2121 "\
2122 POST / HTTP/1.1\r\n\
2123 transfer-encoding: gzip\r\n\
2124 content-length: 10\r\n\
2125 transfer-encoding: chunked\r\n\
2126 \r\n\
2127 ",
2128 );
2129 assert_eq!(msg.decode, DecodedLength::CHUNKED);
2130 assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2131 assert!(!msg.keep_alive);
2132
2133 let msg = parse(
2134 "\
2135 POST / HTTP/1.1\r\n\
2136 connection: keep-alive\r\n\
2137 content-length: 10\r\n\
2138 transfer-encoding: chunked\r\n\
2139 \r\n\
2140 ",
2141 );
2142 assert_eq!(msg.decode, DecodedLength::CHUNKED);
2143 assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
2144 assert!(!msg.keep_alive);
2145
2146 assert_eq!(
2148 parse(
2149 "\
2150 POST / HTTP/1.1\r\n\
2151 content-length: 10\r\n\
2152 content-length: 10\r\n\
2153 \r\n\
2154 "
2155 )
2156 .decode,
2157 DecodedLength::new(10)
2158 );
2159
2160 parse_err(
2162 "\
2163 POST / HTTP/1.1\r\n\
2164 content-length: 10\r\n\
2165 content-length: 11\r\n\
2166 \r\n\
2167 ",
2168 "multiple content-lengths",
2169 );
2170
2171 parse_err(
2173 "\
2174 POST / HTTP/1.1\r\n\
2175 content-length: +10\r\n\
2176 \r\n\
2177 ",
2178 "prefixed content-length",
2179 );
2180
2181 parse_err(
2183 "\
2184 POST / HTTP/1.1\r\n\
2185 transfer-encoding: gzip\r\n\
2186 \r\n\
2187 ",
2188 "transfer-encoding but not chunked",
2189 );
2190
2191 parse_err(
2192 "\
2193 POST / HTTP/1.1\r\n\
2194 transfer-encoding: chunked, gzip\r\n\
2195 \r\n\
2196 ",
2197 "transfer-encoding doesn't end in chunked",
2198 );
2199
2200 parse_err(
2201 "\
2202 POST / HTTP/1.1\r\n\
2203 transfer-encoding: chunked\r\n\
2204 transfer-encoding: afterlol\r\n\
2205 \r\n\
2206 ",
2207 "transfer-encoding multiple lines doesn't end in chunked",
2208 );
2209
2210 assert_eq!(
2213 parse(
2214 "\
2215 POST / HTTP/1.0\r\n\
2216 content-length: 10\r\n\
2217 \r\n\
2218 "
2219 )
2220 .decode,
2221 DecodedLength::new(10)
2222 );
2223
2224 parse_err(
2226 "\
2227 POST / HTTP/1.0\r\n\
2228 transfer-encoding: chunked\r\n\
2229 \r\n\
2230 ",
2231 "1.0 chunked",
2232 );
2233 }
2234
2235 #[test]
2236 fn test_decoder_response() {
2237 fn parse(s: &str) -> ParsedMessage<StatusCode> {
2238 parse_with_method(s, Method::GET)
2239 }
2240
2241 fn parse_ignores(s: &str) {
2242 let mut bytes = BytesMut::from(s);
2243 assert!(Client::parse(
2244 &mut bytes,
2245 ParseContext {
2246 cached_headers: &mut None,
2247 req_method: &mut Some(Method::GET),
2248 h1_parser_config: Default::default(),
2249 h1_max_headers: None,
2250 h1_max_header_size: None,
2251 preserve_header_case: false,
2252 #[cfg(feature = "ffi")]
2253 preserve_header_order: false,
2254 h09_responses: false,
2255 #[cfg(feature = "client")]
2256 on_informational: &mut None,
2257 }
2258 )
2259 .expect("parse ok")
2260 .is_none())
2261 }
2262
2263 fn parse_with_method(s: &str, m: Method) -> ParsedMessage<StatusCode> {
2264 let mut bytes = BytesMut::from(s);
2265 Client::parse(
2266 &mut bytes,
2267 ParseContext {
2268 cached_headers: &mut None,
2269 req_method: &mut Some(m),
2270 h1_parser_config: Default::default(),
2271 h1_max_headers: None,
2272 h1_max_header_size: None,
2273 preserve_header_case: false,
2274 #[cfg(feature = "ffi")]
2275 preserve_header_order: false,
2276 h09_responses: false,
2277 #[cfg(feature = "client")]
2278 on_informational: &mut None,
2279 },
2280 )
2281 .expect("parse ok")
2282 .expect("parse complete")
2283 }
2284
2285 fn parse_err(s: &str) -> crate::error::Parse {
2286 let mut bytes = BytesMut::from(s);
2287 Client::parse(
2288 &mut bytes,
2289 ParseContext {
2290 cached_headers: &mut None,
2291 req_method: &mut Some(Method::GET),
2292 h1_parser_config: Default::default(),
2293 h1_max_headers: None,
2294 h1_max_header_size: None,
2295 preserve_header_case: false,
2296 #[cfg(feature = "ffi")]
2297 preserve_header_order: false,
2298 h09_responses: false,
2299 #[cfg(feature = "client")]
2300 on_informational: &mut None,
2301 },
2302 )
2303 .expect_err("parse should err")
2304 }
2305
2306 assert_eq!(
2308 parse(
2309 "\
2310 HTTP/1.1 200 OK\r\n\
2311 \r\n\
2312 "
2313 )
2314 .decode,
2315 DecodedLength::CLOSE_DELIMITED
2316 );
2317
2318 assert_eq!(
2320 parse(
2321 "\
2322 HTTP/1.1 204 No Content\r\n\
2323 \r\n\
2324 "
2325 )
2326 .decode,
2327 DecodedLength::ZERO
2328 );
2329
2330 assert_eq!(
2331 parse(
2332 "\
2333 HTTP/1.1 304 Not Modified\r\n\
2334 \r\n\
2335 "
2336 )
2337 .decode,
2338 DecodedLength::ZERO
2339 );
2340
2341 assert_eq!(
2343 parse(
2344 "\
2345 HTTP/1.1 200 OK\r\n\
2346 content-length: 8\r\n\
2347 \r\n\
2348 "
2349 )
2350 .decode,
2351 DecodedLength::new(8)
2352 );
2353
2354 assert_eq!(
2355 parse(
2356 "\
2357 HTTP/1.1 200 OK\r\n\
2358 content-length: 8\r\n\
2359 content-length: 8\r\n\
2360 \r\n\
2361 "
2362 )
2363 .decode,
2364 DecodedLength::new(8)
2365 );
2366
2367 parse_err(
2368 "\
2369 HTTP/1.1 200 OK\r\n\
2370 content-length: 8\r\n\
2371 content-length: 9\r\n\
2372 \r\n\
2373 ",
2374 );
2375
2376 parse_err(
2377 "\
2378 HTTP/1.1 200 OK\r\n\
2379 content-length: +8\r\n\
2380 \r\n\
2381 ",
2382 );
2383
2384 assert_eq!(
2386 parse(
2387 "\
2388 HTTP/1.1 200 OK\r\n\
2389 transfer-encoding: chunked\r\n\
2390 \r\n\
2391 "
2392 )
2393 .decode,
2394 DecodedLength::CHUNKED
2395 );
2396
2397 assert_eq!(
2399 parse(
2400 "\
2401 HTTP/1.1 200 OK\r\n\
2402 transfer-encoding: yolo\r\n\
2403 \r\n\
2404 "
2405 )
2406 .decode,
2407 DecodedLength::CLOSE_DELIMITED
2408 );
2409
2410 assert_eq!(
2412 parse(
2413 "\
2414 HTTP/1.1 200 OK\r\n\
2415 content-length: 10\r\n\
2416 transfer-encoding: chunked\r\n\
2417 \r\n\
2418 "
2419 )
2420 .decode,
2421 DecodedLength::CHUNKED
2422 );
2423
2424 assert_eq!(
2426 parse_with_method(
2427 "\
2428 HTTP/1.1 200 OK\r\n\
2429 content-length: 8\r\n\
2430 \r\n\
2431 ",
2432 Method::HEAD
2433 )
2434 .decode,
2435 DecodedLength::ZERO
2436 );
2437
2438 {
2440 let msg = parse_with_method(
2441 "\
2442 HTTP/1.1 200 OK\r\n\
2443 \r\n\
2444 ",
2445 Method::CONNECT,
2446 );
2447 assert_eq!(msg.decode, DecodedLength::ZERO);
2448 assert!(!msg.keep_alive, "should be upgrade");
2449 assert!(msg.wants_upgrade, "should be upgrade");
2450 }
2451
2452 assert_eq!(
2454 parse_with_method(
2455 "\
2456 HTTP/1.1 400 Bad Request\r\n\
2457 \r\n\
2458 ",
2459 Method::CONNECT
2460 )
2461 .decode,
2462 DecodedLength::CLOSE_DELIMITED
2463 );
2464
2465 parse_ignores(
2467 "\
2468 HTTP/1.1 100 Continue\r\n\
2469 \r\n\
2470 ",
2471 );
2472
2473 parse_ignores(
2474 "\
2475 HTTP/1.1 103 Early Hints\r\n\
2476 \r\n\
2477 ",
2478 );
2479
2480 {
2482 let msg = parse(
2483 "\
2484 HTTP/1.1 101 Switching Protocols\r\n\
2485 \r\n\
2486 ",
2487 );
2488 assert_eq!(msg.decode, DecodedLength::ZERO);
2489 assert!(!msg.keep_alive, "should be last");
2490 assert!(msg.wants_upgrade, "should be upgrade");
2491 }
2492
2493 assert_eq!(
2495 parse(
2496 "\
2497 HTTP/1.0 200 OK\r\n\
2498 \r\n\
2499 "
2500 )
2501 .decode,
2502 DecodedLength::CLOSE_DELIMITED
2503 );
2504
2505 parse_err(
2507 "\
2508 HTTP/1.0 200 OK\r\n\
2509 transfer-encoding: chunked\r\n\
2510 \r\n\
2511 ",
2512 );
2513
2514 assert!(
2516 parse(
2517 "\
2518 HTTP/1.1 200 OK\r\n\
2519 content-length: 0\r\n\
2520 \r\n\
2521 "
2522 )
2523 .keep_alive,
2524 "HTTP/1.1 keep-alive is default"
2525 );
2526
2527 assert!(
2528 !parse(
2529 "\
2530 HTTP/1.1 200 OK\r\n\
2531 content-length: 0\r\n\
2532 connection: foo, close, bar\r\n\
2533 \r\n\
2534 "
2535 )
2536 .keep_alive,
2537 "connection close is always close"
2538 );
2539
2540 assert!(
2541 !parse(
2542 "\
2543 HTTP/1.0 200 OK\r\n\
2544 content-length: 0\r\n\
2545 \r\n\
2546 "
2547 )
2548 .keep_alive,
2549 "HTTP/1.0 close is default"
2550 );
2551
2552 assert!(
2553 parse(
2554 "\
2555 HTTP/1.0 200 OK\r\n\
2556 content-length: 0\r\n\
2557 connection: foo, keep-alive, bar\r\n\
2558 \r\n\
2559 "
2560 )
2561 .keep_alive,
2562 "connection keep-alive is always keep-alive"
2563 );
2564 }
2565
2566 #[cfg(feature = "server")]
2567 #[test]
2568 fn test_parse_request_multiple_connection_headers() {
2569 fn parse(s: &str) -> ParsedMessage<RequestLine> {
2570 let mut bytes = BytesMut::from(s);
2571 Server::parse(
2572 &mut bytes,
2573 ParseContext {
2574 cached_headers: &mut None,
2575 req_method: &mut None,
2576 h1_parser_config: Default::default(),
2577 h1_max_headers: None,
2578 h1_max_header_size: None,
2579 preserve_header_case: false,
2580 #[cfg(feature = "ffi")]
2581 preserve_header_order: false,
2582 h09_responses: false,
2583 #[cfg(feature = "client")]
2584 on_informational: &mut None,
2585 },
2586 )
2587 .unwrap()
2588 .unwrap()
2589 }
2590
2591 assert!(
2592 !parse(
2593 "\
2594 GET / HTTP/1.1\r\n\
2595 connection: close\r\n\
2596 connection: keep-alive\r\n\
2597 \r\n\
2598 "
2599 )
2600 .keep_alive,
2601 "close before keep-alive is still close"
2602 );
2603
2604 assert!(
2605 !parse(
2606 "\
2607 GET / HTTP/1.1\r\n\
2608 connection: keep-alive\r\n\
2609 connection: close\r\n\
2610 \r\n\
2611 "
2612 )
2613 .keep_alive,
2614 "keep-alive before close is still close"
2615 );
2616
2617 assert!(
2618 parse(
2619 "\
2620 GET / HTTP/1.0\r\n\
2621 connection: keep-alive\r\n\
2622 connection: foo\r\n\
2623 \r\n\
2624 "
2625 )
2626 .keep_alive,
2627 "HTTP/1.0 keep-alive is not undone by an unrelated token"
2628 );
2629
2630 assert!(
2631 !parse(
2632 "\
2633 GET / HTTP/1.0\r\n\
2634 connection: keep-alive\r\n\
2635 connection: close\r\n\
2636 \r\n\
2637 "
2638 )
2639 .keep_alive,
2640 "HTTP/1.0 close wins over an earlier keep-alive"
2641 );
2642 }
2643
2644 #[cfg(feature = "client")]
2645 #[test]
2646 fn test_parse_response_multiple_connection_headers() {
2647 fn parse(s: &str) -> ParsedMessage<StatusCode> {
2648 let mut bytes = BytesMut::from(s);
2649 Client::parse(
2650 &mut bytes,
2651 ParseContext {
2652 cached_headers: &mut None,
2653 req_method: &mut Some(Method::GET),
2654 h1_parser_config: Default::default(),
2655 h1_max_headers: None,
2656 h1_max_header_size: None,
2657 preserve_header_case: false,
2658 #[cfg(feature = "ffi")]
2659 preserve_header_order: false,
2660 h09_responses: false,
2661 #[cfg(feature = "client")]
2662 on_informational: &mut None,
2663 },
2664 )
2665 .unwrap()
2666 .unwrap()
2667 }
2668
2669 assert!(
2670 !parse(
2671 "\
2672 HTTP/1.1 200 OK\r\n\
2673 content-length: 0\r\n\
2674 connection: close\r\n\
2675 connection: keep-alive\r\n\
2676 \r\n\
2677 "
2678 )
2679 .keep_alive,
2680 "close before keep-alive is still close"
2681 );
2682
2683 assert!(
2684 !parse(
2685 "\
2686 HTTP/1.1 200 OK\r\n\
2687 content-length: 0\r\n\
2688 connection: keep-alive\r\n\
2689 connection: close\r\n\
2690 \r\n\
2691 "
2692 )
2693 .keep_alive,
2694 "keep-alive before close is still close"
2695 );
2696
2697 assert!(
2698 parse(
2699 "\
2700 HTTP/1.0 200 OK\r\n\
2701 content-length: 0\r\n\
2702 connection: keep-alive\r\n\
2703 connection: foo\r\n\
2704 \r\n\
2705 "
2706 )
2707 .keep_alive,
2708 "HTTP/1.0 keep-alive is not undone by an unrelated token"
2709 );
2710
2711 assert!(
2712 !parse(
2713 "\
2714 HTTP/1.0 200 OK\r\n\
2715 content-length: 0\r\n\
2716 connection: keep-alive\r\n\
2717 connection: close\r\n\
2718 \r\n\
2719 "
2720 )
2721 .keep_alive,
2722 "HTTP/1.0 close wins over an earlier keep-alive"
2723 );
2724 }
2725
2726 #[cfg(feature = "client")]
2727 #[test]
2728 fn test_client_obs_fold_line() {
2729 fn unfold(src: &str) -> String {
2730 let mut buf = src.as_bytes().to_vec();
2731 let mut idx = HeaderIndices {
2732 name: (0, 0),
2733 value: (0, buf.len()),
2734 };
2735 Client::obs_fold_line(&mut buf, &mut idx);
2736 String::from_utf8(buf[idx.value.0..idx.value.1].to_vec()).unwrap()
2737 }
2738
2739 assert_eq!(unfold("a normal line"), "a normal line",);
2740
2741 assert_eq!(unfold("obs\r\n fold\r\n\t line"), "obs fold line",);
2742 }
2743
2744 #[test]
2745 fn test_client_request_encode_explicit_transfer_encoding_removes_content_length() {
2746 use crate::proto::BodyLength;
2747 use http::header::HeaderValue;
2748
2749 for values in [
2750 vec!["10"],
2751 vec![""],
2752 vec!["abc"],
2753 vec!["+10"],
2754 vec!["18446744073709551616"],
2755 vec!["10", "11"],
2756 vec!["10, 11"],
2757 vec!["10", "abc"],
2758 ] {
2759 for transfer_encoding in ["chunked", "gzip"] {
2760 for body in [BodyLength::Known(10), BodyLength::Unknown] {
2761 let mut head = MessageHead::default();
2762 for value in &values {
2763 head.headers
2764 .append("content-length", HeaderValue::from_static(value));
2765 }
2766 head.headers.insert(
2767 "transfer-encoding",
2768 HeaderValue::from_static(transfer_encoding),
2769 );
2770
2771 let mut vec = Vec::new();
2772 let encoder = Client::encode(
2773 Encode {
2774 head: &mut head,
2775 body: Some(body),
2776 #[cfg(feature = "server")]
2777 keep_alive: true,
2778 req_method: &mut None,
2779 title_case_headers: false,
2780 #[cfg(feature = "server")]
2781 date_header: true,
2782 },
2783 &mut vec,
2784 )
2785 .unwrap();
2786
2787 assert!(encoder.is_chunked());
2788 let expected_te = if transfer_encoding == "chunked" {
2789 "chunked"
2790 } else {
2791 "gzip, chunked"
2792 };
2793 assert_eq!(
2794 vec,
2795 format!("GET / HTTP/1.1\r\ntransfer-encoding: {expected_te}\r\n\r\n")
2796 .as_bytes(),
2797 "content-length: {values:?}, transfer-encoding: {transfer_encoding}"
2798 );
2799 }
2800 }
2801 }
2802 }
2803
2804 #[test]
2805 fn test_client_request_encode_automatic_transfer_encoding_removes_content_length() {
2806 use crate::proto::BodyLength;
2807 use http::header::HeaderValue;
2808
2809 for values in [
2810 vec![],
2811 vec![""],
2812 vec!["abc"],
2813 vec!["+10"],
2814 vec!["18446744073709551616"],
2815 vec!["10", "11"],
2816 vec!["10, 11"],
2817 vec!["10", "abc"],
2818 vec!["10"],
2819 ] {
2820 let mut head = RequestHead::default();
2821 head.subject.0 = Method::POST;
2822 for value in &values {
2823 head.headers
2824 .append("content-length", HeaderValue::from_static(value));
2825 }
2826
2827 let mut vec = Vec::new();
2828 let encoder = Client::encode(
2829 Encode {
2830 head: &mut head,
2831 body: Some(BodyLength::Unknown),
2832 #[cfg(feature = "server")]
2833 keep_alive: true,
2834 req_method: &mut None,
2835 title_case_headers: false,
2836 #[cfg(feature = "server")]
2837 date_header: true,
2838 },
2839 &mut vec,
2840 )
2841 .unwrap();
2842
2843 if values == ["10"] {
2844 assert_eq!(encoder, Encoder::length(10));
2845 assert_eq!(vec, b"POST / HTTP/1.1\r\ncontent-length: 10\r\n\r\n");
2846 } else {
2847 assert!(encoder.is_chunked());
2848 assert_eq!(
2849 vec, b"POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n",
2850 "content-length: {values:?}"
2851 );
2852 }
2853 }
2854 }
2855
2856 #[test]
2857 fn test_client_request_encode_title_case() {
2858 use crate::proto::BodyLength;
2859 use http::header::HeaderValue;
2860
2861 let mut head = MessageHead::default();
2862 head.headers
2863 .insert("content-length", HeaderValue::from_static("10"));
2864 head.headers
2865 .insert("content-type", HeaderValue::from_static("application/json"));
2866 head.headers.insert("*-*", HeaderValue::from_static("o_o"));
2867
2868 let mut vec = Vec::new();
2869 Client::encode(
2870 Encode {
2871 head: &mut head,
2872 body: Some(BodyLength::Known(10)),
2873 #[cfg(feature = "server")]
2874 keep_alive: true,
2875 req_method: &mut None,
2876 title_case_headers: true,
2877 #[cfg(feature = "server")]
2878 date_header: true,
2879 },
2880 &mut vec,
2881 )
2882 .unwrap();
2883
2884 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());
2885 }
2886
2887 #[test]
2888 fn test_client_request_encode_orig_case() {
2889 use crate::proto::BodyLength;
2890 use http::header::{HeaderValue, CONTENT_LENGTH};
2891
2892 let mut head = MessageHead::default();
2893 head.headers
2894 .insert("content-length", HeaderValue::from_static("10"));
2895 head.headers
2896 .insert("content-type", HeaderValue::from_static("application/json"));
2897
2898 let mut orig_headers = HeaderCaseMap::default();
2899 orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2900 head.extensions.insert(orig_headers);
2901
2902 let mut vec = Vec::new();
2903 Client::encode(
2904 Encode {
2905 head: &mut head,
2906 body: Some(BodyLength::Known(10)),
2907 #[cfg(feature = "server")]
2908 keep_alive: true,
2909 req_method: &mut None,
2910 title_case_headers: false,
2911 #[cfg(feature = "server")]
2912 date_header: true,
2913 },
2914 &mut vec,
2915 )
2916 .unwrap();
2917
2918 assert_eq!(
2919 &*vec,
2920 b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\n\r\n"
2921 .as_ref(),
2922 );
2923 }
2924 #[test]
2925 fn test_client_request_encode_orig_and_title_case() {
2926 use crate::proto::BodyLength;
2927 use http::header::{HeaderValue, CONTENT_LENGTH};
2928
2929 let mut head = MessageHead::default();
2930 head.headers
2931 .insert("content-length", HeaderValue::from_static("10"));
2932 head.headers
2933 .insert("content-type", HeaderValue::from_static("application/json"));
2934
2935 let mut orig_headers = HeaderCaseMap::default();
2936 orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2937 head.extensions.insert(orig_headers);
2938
2939 let mut vec = Vec::new();
2940 Client::encode(
2941 Encode {
2942 head: &mut head,
2943 body: Some(BodyLength::Known(10)),
2944 #[cfg(feature = "server")]
2945 keep_alive: true,
2946 req_method: &mut None,
2947 title_case_headers: true,
2948 #[cfg(feature = "server")]
2949 date_header: true,
2950 },
2951 &mut vec,
2952 )
2953 .unwrap();
2954
2955 assert_eq!(
2956 &*vec,
2957 b"GET / HTTP/1.1\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\n\r\n"
2958 .as_ref(),
2959 );
2960 }
2961
2962 #[cfg(feature = "server")]
2963 #[test]
2964 fn test_server_encode_connect_method() {
2965 let mut head = MessageHead::default();
2966
2967 let mut vec = Vec::new();
2968 let encoder = Server::encode(
2969 Encode {
2970 head: &mut head,
2971 body: None,
2972 keep_alive: true,
2973 req_method: &mut Some(Method::CONNECT),
2974 title_case_headers: false,
2975 date_header: true,
2976 },
2977 &mut vec,
2978 )
2979 .unwrap();
2980
2981 assert!(encoder.is_last());
2982 }
2983
2984 #[cfg(feature = "server")]
2985 #[test]
2986 fn test_server_response_encode_title_case() {
2987 use crate::proto::BodyLength;
2988 use http::header::HeaderValue;
2989
2990 let mut head = MessageHead::default();
2991 head.headers
2992 .insert("content-length", HeaderValue::from_static("10"));
2993 head.headers
2994 .insert("content-type", HeaderValue::from_static("application/json"));
2995 head.headers
2996 .insert("weird--header", HeaderValue::from_static(""));
2997
2998 let mut vec = Vec::new();
2999 Server::encode(
3000 Encode {
3001 head: &mut head,
3002 body: Some(BodyLength::Known(10)),
3003 keep_alive: true,
3004 req_method: &mut None,
3005 title_case_headers: true,
3006 date_header: true,
3007 },
3008 &mut vec,
3009 )
3010 .unwrap();
3011
3012 let expected_response =
3013 b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: application/json\r\nWeird--Header: \r\n";
3014
3015 assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
3016 }
3017
3018 #[cfg(feature = "server")]
3019 #[test]
3020 fn test_server_response_encode_orig_case() {
3021 use crate::proto::BodyLength;
3022 use http::header::{HeaderValue, CONTENT_LENGTH};
3023
3024 let mut head = MessageHead::default();
3025 head.headers
3026 .insert("content-length", HeaderValue::from_static("10"));
3027 head.headers
3028 .insert("content-type", HeaderValue::from_static("application/json"));
3029
3030 let mut orig_headers = HeaderCaseMap::default();
3031 orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
3032 head.extensions.insert(orig_headers);
3033
3034 let mut vec = Vec::new();
3035 Server::encode(
3036 Encode {
3037 head: &mut head,
3038 body: Some(BodyLength::Known(10)),
3039 keep_alive: true,
3040 req_method: &mut None,
3041 title_case_headers: false,
3042 date_header: true,
3043 },
3044 &mut vec,
3045 )
3046 .unwrap();
3047
3048 let expected_response =
3049 b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\ncontent-type: application/json\r\ndate: ";
3050
3051 assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
3052 }
3053
3054 #[cfg(feature = "server")]
3055 #[test]
3056 fn test_server_response_encode_orig_and_title_case() {
3057 use crate::proto::BodyLength;
3058 use http::header::{HeaderValue, CONTENT_LENGTH};
3059
3060 let mut head = MessageHead::default();
3061 head.headers
3062 .insert("content-length", HeaderValue::from_static("10"));
3063 head.headers
3064 .insert("content-type", HeaderValue::from_static("application/json"));
3065
3066 let mut orig_headers = HeaderCaseMap::default();
3067 orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
3068 head.extensions.insert(orig_headers);
3069
3070 let mut vec = Vec::new();
3071 Server::encode(
3072 Encode {
3073 head: &mut head,
3074 body: Some(BodyLength::Known(10)),
3075 keep_alive: true,
3076 req_method: &mut None,
3077 title_case_headers: true,
3078 date_header: true,
3079 },
3080 &mut vec,
3081 )
3082 .unwrap();
3083
3084 let expected_response =
3086 b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\nDate: ";
3087
3088 assert_eq!(&vec[..expected_response.len()], &expected_response[..]);
3089 }
3090
3091 #[cfg(feature = "server")]
3092 #[test]
3093 fn test_disabled_date_header() {
3094 use crate::proto::BodyLength;
3095 use http::header::{HeaderValue, CONTENT_LENGTH};
3096
3097 let mut head = MessageHead::default();
3098 head.headers
3099 .insert("content-length", HeaderValue::from_static("10"));
3100 head.headers
3101 .insert("content-type", HeaderValue::from_static("application/json"));
3102
3103 let mut orig_headers = HeaderCaseMap::default();
3104 orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
3105 head.extensions.insert(orig_headers);
3106
3107 let mut vec = Vec::new();
3108 Server::encode(
3109 Encode {
3110 head: &mut head,
3111 body: Some(BodyLength::Known(10)),
3112 keep_alive: true,
3113 req_method: &mut None,
3114 title_case_headers: true,
3115 date_header: false,
3116 },
3117 &mut vec,
3118 )
3119 .unwrap();
3120
3121 let expected_response =
3122 b"HTTP/1.1 200 OK\r\nCONTENT-LENGTH: 10\r\nContent-Type: application/json\r\n\r\n";
3123
3124 assert_eq!(&vec, &expected_response);
3125 }
3126
3127 #[test]
3128 fn parse_header_htabs() {
3129 let mut bytes = BytesMut::from("HTTP/1.1 200 OK\r\nserver: hello\tworld\r\n\r\n");
3130 let parsed = Client::parse(
3131 &mut bytes,
3132 ParseContext {
3133 cached_headers: &mut None,
3134 req_method: &mut Some(Method::GET),
3135 h1_parser_config: Default::default(),
3136 h1_max_headers: None,
3137 h1_max_header_size: None,
3138 preserve_header_case: false,
3139 #[cfg(feature = "ffi")]
3140 preserve_header_order: false,
3141 h09_responses: false,
3142 #[cfg(feature = "client")]
3143 on_informational: &mut None,
3144 },
3145 )
3146 .expect("parse ok")
3147 .expect("parse complete");
3148
3149 assert_eq!(parsed.head.headers["server"], "hello\tworld");
3150 }
3151
3152 #[cfg(feature = "server")]
3153 #[test]
3154 fn parse_too_large_headers() {
3155 fn gen_req_with_headers(num: usize) -> String {
3156 let mut req = String::from("GET / HTTP/1.1\r\n");
3157 for i in 0..num {
3158 req.push_str(&format!("key{i}: val{i}\r\n"));
3159 }
3160 req.push_str("\r\n");
3161 req
3162 }
3163 fn gen_resp_with_headers(num: usize) -> String {
3164 let mut req = String::from("HTTP/1.1 200 OK\r\n");
3165 for i in 0..num {
3166 req.push_str(&format!("key{i}: val{i}\r\n"));
3167 }
3168 req.push_str("\r\n");
3169 req
3170 }
3171 fn parse(max_headers: Option<usize>, gen_size: usize, should_success: bool) {
3172 {
3173 let mut bytes = BytesMut::from(gen_req_with_headers(gen_size).as_str());
3175 let result = Server::parse(
3176 &mut bytes,
3177 ParseContext {
3178 cached_headers: &mut None,
3179 req_method: &mut None,
3180 h1_parser_config: Default::default(),
3181 h1_max_headers: max_headers,
3182 h1_max_header_size: None,
3183 preserve_header_case: false,
3184 #[cfg(feature = "ffi")]
3185 preserve_header_order: false,
3186 h09_responses: false,
3187 #[cfg(feature = "client")]
3188 on_informational: &mut None,
3189 },
3190 );
3191 if should_success {
3192 result.expect("parse ok").expect("parse complete");
3193 } else {
3194 result.expect_err("parse should err");
3195 }
3196 }
3197 {
3198 let mut bytes = BytesMut::from(gen_resp_with_headers(gen_size).as_str());
3200 let result = Client::parse(
3201 &mut bytes,
3202 ParseContext {
3203 cached_headers: &mut None,
3204 req_method: &mut None,
3205 h1_parser_config: Default::default(),
3206 h1_max_headers: max_headers,
3207 h1_max_header_size: None,
3208 preserve_header_case: false,
3209 #[cfg(feature = "ffi")]
3210 preserve_header_order: false,
3211 h09_responses: false,
3212 #[cfg(feature = "client")]
3213 on_informational: &mut None,
3214 },
3215 );
3216 if should_success {
3217 result.expect("parse ok").expect("parse complete");
3218 } else {
3219 result.expect_err("parse should err");
3220 }
3221 }
3222 }
3223
3224 assert_eq!(
3226 gen_req_with_headers(0),
3227 String::from("GET / HTTP/1.1\r\n\r\n")
3228 );
3229 assert_eq!(
3230 gen_req_with_headers(1),
3231 String::from("GET / HTTP/1.1\r\nkey0: val0\r\n\r\n")
3232 );
3233 assert_eq!(
3234 gen_req_with_headers(2),
3235 String::from("GET / HTTP/1.1\r\nkey0: val0\r\nkey1: val1\r\n\r\n")
3236 );
3237 assert_eq!(
3238 gen_req_with_headers(3),
3239 String::from("GET / HTTP/1.1\r\nkey0: val0\r\nkey1: val1\r\nkey2: val2\r\n\r\n")
3240 );
3241
3242 parse(None, 0, true);
3247 parse(None, 1, true);
3248 parse(None, 50, true);
3249 parse(None, 99, true);
3250 parse(None, 100, true);
3251 parse(None, 101, false);
3255 parse(None, 102, false);
3256 parse(None, 200, false);
3257
3258 parse(Some(0), 0, true);
3263 parse(Some(0), 1, false);
3267 parse(Some(0), 100, false);
3268
3269 parse(Some(200), 0, true);
3274 parse(Some(200), 1, true);
3275 parse(Some(200), 100, true);
3276 parse(Some(200), 200, true);
3277 parse(Some(200), 201, false);
3281 parse(Some(200), 210, false);
3282 }
3283
3284 #[test]
3285 #[cfg(feature = "server")]
3286 fn test_h1_server_max_header_size() {
3287 let _ = pretty_env_logger::try_init();
3288
3289 let req_str = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
3290 assert_eq!(req_str.len(), 37);
3291
3292 let parse_req = |max_header_size: Option<usize>| {
3293 let mut bytes = BytesMut::from(req_str);
3294 Server::parse(
3295 &mut bytes,
3296 ParseContext {
3297 cached_headers: &mut None,
3298 req_method: &mut None,
3299 h1_parser_config: Default::default(),
3300 h1_max_headers: None,
3301 h1_max_header_size: max_header_size,
3302 preserve_header_case: false,
3303 #[cfg(feature = "ffi")]
3304 preserve_header_order: false,
3305 h09_responses: false,
3306 #[cfg(feature = "client")]
3307 on_informational: &mut None,
3308 },
3309 )
3310 };
3311
3312 parse_req(None).unwrap().unwrap();
3314 parse_req(Some(37)).unwrap().unwrap();
3315 parse_req(Some(50)).unwrap().unwrap();
3316 assert!(matches!(parse_req(Some(36)), Err(Parse::TooLarge)));
3317 assert!(matches!(parse_req(Some(10)), Err(Parse::TooLarge)));
3318 }
3319
3320 #[test]
3321 #[cfg(feature = "client")]
3322 fn test_h1_client_max_header_size() {
3323 let _ = pretty_env_logger::try_init();
3324
3325 let resp_str = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
3326 assert_eq!(resp_str.len(), 38);
3327
3328 let parse_resp = |max_header_size: Option<usize>| {
3329 let mut bytes = BytesMut::from(resp_str);
3330 Client::parse(
3331 &mut bytes,
3332 ParseContext {
3333 cached_headers: &mut None,
3334 req_method: &mut None,
3335 h1_parser_config: Default::default(),
3336 h1_max_headers: None,
3337 h1_max_header_size: max_header_size,
3338 preserve_header_case: false,
3339 #[cfg(feature = "ffi")]
3340 preserve_header_order: false,
3341 h09_responses: false,
3342 #[cfg(feature = "client")]
3343 on_informational: &mut None,
3344 },
3345 )
3346 };
3347
3348 parse_resp(None).unwrap().unwrap();
3350 parse_resp(Some(38)).unwrap().unwrap();
3351 parse_resp(Some(50)).unwrap().unwrap();
3352 assert!(matches!(parse_resp(Some(37)), Err(Parse::TooLarge)));
3353 assert!(matches!(parse_resp(Some(10)), Err(Parse::TooLarge)));
3354 }
3355
3356 #[test]
3357 fn test_is_complete_fast() {
3358 let s = b"GET / HTTP/1.1\r\na: b\r\n\r\n";
3359 for n in 0..s.len() {
3360 assert!(is_complete_fast(s, n), "{:?}; {}", s, n);
3361 }
3362 let s = b"GET / HTTP/1.1\na: b\n\n";
3363 for n in 0..s.len() {
3364 assert!(is_complete_fast(s, n));
3365 }
3366 let s = b"GET / HTTP/1.1\r\na: b\n\r\n";
3367 for n in 0..s.len() {
3368 assert!(is_complete_fast(s, n), "{:?}; {}", s, n);
3369 }
3370
3371 let s = b"GET / HTTP/1.1\r\na: b\r\n\r";
3373 for n in 0..s.len() {
3374 assert!(!is_complete_fast(s, n));
3375 }
3376 let s = b"GET / HTTP/1.1\na: b\n";
3377 for n in 0..s.len() {
3378 assert!(!is_complete_fast(s, n));
3379 }
3380 let s = b"GET / HTTP/1.1\r\na: b\n\r";
3381 for n in 0..s.len() {
3382 assert!(!is_complete_fast(s, n));
3383 }
3384 }
3385
3386 #[cfg(feature = "server")]
3387 #[test]
3388 fn test_parse_accepts_lf_crlf_terminator() {
3389 let mut bytes = BytesMut::from("GET / HTTP/1.1\r\na: b\n\r\n");
3393 Server::parse(
3394 &mut bytes,
3395 ParseContext {
3396 cached_headers: &mut None,
3397 req_method: &mut None,
3398 h1_parser_config: Default::default(),
3399 h1_max_headers: None,
3400 h1_max_header_size: None,
3401 preserve_header_case: false,
3402 #[cfg(feature = "ffi")]
3403 preserve_header_order: false,
3404 h09_responses: false,
3405 #[cfg(feature = "client")]
3406 on_informational: &mut None,
3407 },
3408 )
3409 .expect("parse ok")
3410 .expect("parse complete");
3411 }
3412
3413 #[test]
3414 fn test_write_headers_orig_case_empty_value() {
3415 let mut headers = HeaderMap::new();
3416 let name = http::header::HeaderName::from_static("x-empty");
3417 headers.insert(&name, "".parse().expect("parse empty"));
3418 let mut orig_cases = HeaderCaseMap::default();
3419 orig_cases.insert(name, Bytes::from_static(b"X-EmptY"));
3420
3421 let mut dst = Vec::new();
3422 super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
3423
3424 assert_eq!(
3425 dst, b"X-EmptY:\r\n",
3426 "there should be no space between the colon and CRLF"
3427 );
3428 }
3429
3430 #[test]
3431 fn test_write_headers_orig_case_multiple_entries() {
3432 let mut headers = HeaderMap::new();
3433 let name = http::header::HeaderName::from_static("x-empty");
3434 headers.insert(&name, "a".parse().unwrap());
3435 headers.append(&name, "b".parse().unwrap());
3436
3437 let mut orig_cases = HeaderCaseMap::default();
3438 orig_cases.insert(name.clone(), Bytes::from_static(b"X-Empty"));
3439 orig_cases.append(name, Bytes::from_static(b"X-EMPTY"));
3440
3441 let mut dst = Vec::new();
3442 super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
3443
3444 assert_eq!(dst, b"X-Empty: a\r\nX-EMPTY: b\r\n");
3445 }
3446
3447 #[cfg(feature = "nightly")]
3448 use test::Bencher;
3449
3450 #[cfg(feature = "nightly")]
3451 #[bench]
3452 fn bench_parse_incoming(b: &mut Bencher) {
3453 let mut raw = BytesMut::from(
3454 &b"GET /super_long_uri/and_whatever?what_should_we_talk_about/\
3455 I_wonder/Hard_to_write_in_an_uri_after_all/you_have_to_make\
3456 _up_the_punctuation_yourself/how_fun_is_that?test=foo&test1=\
3457 foo1&test2=foo2&test3=foo3&test4=foo4 HTTP/1.1\r\nHost: \
3458 hyper.rs\r\nAccept: a lot of things\r\nAccept-Charset: \
3459 utf8\r\nAccept-Encoding: *\r\nAccess-Control-Allow-\
3460 Credentials: None\r\nAccess-Control-Allow-Origin: None\r\n\
3461 Access-Control-Allow-Methods: None\r\nAccess-Control-Allow-\
3462 Headers: None\r\nContent-Encoding: utf8\r\nContent-Security-\
3463 Policy: None\r\nContent-Type: text/html\r\nOrigin: hyper\
3464 \r\nSec-Websocket-Extensions: It looks super important!\r\n\
3465 Sec-Websocket-Origin: hyper\r\nSec-Websocket-Version: 4.3\r\
3466 \nStrict-Transport-Security: None\r\nUser-Agent: hyper\r\n\
3467 X-Content-Duration: None\r\nX-Content-Security-Policy: None\
3468 \r\nX-DNSPrefetch-Control: None\r\nX-Frame-Options: \
3469 Something important obviously\r\nX-Requested-With: Nothing\
3470 \r\n\r\n"[..],
3471 );
3472 let len = raw.len();
3473 let mut headers = Some(HeaderMap::new());
3474
3475 b.bytes = len as u64;
3476 b.iter(|| {
3477 let mut msg = Server::parse(
3478 &mut raw,
3479 ParseContext {
3480 cached_headers: &mut headers,
3481 req_method: &mut None,
3482 h1_parser_config: Default::default(),
3483 h1_max_headers: None,
3484 h1_max_header_size: None,
3485 preserve_header_case: false,
3486 #[cfg(feature = "ffi")]
3487 preserve_header_order: false,
3488 h09_responses: false,
3489 #[cfg(feature = "client")]
3490 on_informational: &mut None,
3491 },
3492 )
3493 .unwrap()
3494 .unwrap();
3495 ::test::black_box(&msg);
3496
3497 msg.head.headers.clear();
3499 headers = Some(msg.head.headers);
3500 std::mem::take(&mut msg.head.subject);
3501
3502 restart(&mut raw, len);
3503 });
3504
3505 fn restart(b: &mut BytesMut, len: usize) {
3506 b.reserve(1);
3507 unsafe {
3508 b.set_len(len);
3509 }
3510 }
3511 }
3512
3513 #[cfg(feature = "nightly")]
3514 #[bench]
3515 fn bench_parse_short(b: &mut Bencher) {
3516 let s = &b"GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"[..];
3517 let mut raw = BytesMut::from(s);
3518 let len = raw.len();
3519 let mut headers = Some(HeaderMap::new());
3520
3521 b.bytes = len as u64;
3522 b.iter(|| {
3523 let mut msg = Server::parse(
3524 &mut raw,
3525 ParseContext {
3526 cached_headers: &mut headers,
3527 req_method: &mut None,
3528 h1_parser_config: Default::default(),
3529 h1_max_headers: None,
3530 h1_max_header_size: None,
3531 preserve_header_case: false,
3532 #[cfg(feature = "ffi")]
3533 preserve_header_order: false,
3534 h09_responses: false,
3535 #[cfg(feature = "client")]
3536 on_informational: &mut None,
3537 },
3538 )
3539 .unwrap()
3540 .unwrap();
3541 ::test::black_box(&msg);
3542 msg.head.headers.clear();
3543 headers = Some(msg.head.headers);
3544 restart(&mut raw, len);
3545 });
3546
3547 fn restart(b: &mut BytesMut, len: usize) {
3548 b.reserve(1);
3549 unsafe {
3550 b.set_len(len);
3551 }
3552 }
3553 }
3554
3555 #[cfg(feature = "nightly")]
3556 #[bench]
3557 fn bench_server_encode_headers_preset(b: &mut Bencher) {
3558 use crate::proto::BodyLength;
3559 use http::header::HeaderValue;
3560
3561 let len = 108;
3562 b.bytes = len as u64;
3563
3564 let mut head = MessageHead::default();
3565 let mut headers = HeaderMap::new();
3566 headers.insert("content-length", HeaderValue::from_static("10"));
3567 headers.insert("content-type", HeaderValue::from_static("application/json"));
3568
3569 b.iter(|| {
3570 let mut vec = Vec::new();
3571 head.headers = headers.clone();
3572 Server::encode(
3573 Encode {
3574 head: &mut head,
3575 body: Some(BodyLength::Known(10)),
3576 keep_alive: true,
3577 req_method: &mut Some(Method::GET),
3578 title_case_headers: false,
3579 date_header: true,
3580 },
3581 &mut vec,
3582 )
3583 .unwrap();
3584 assert_eq!(vec.len(), len);
3585 ::test::black_box(vec);
3586 })
3587 }
3588
3589 #[cfg(feature = "nightly")]
3590 #[bench]
3591 fn bench_server_encode_no_headers(b: &mut Bencher) {
3592 use crate::proto::BodyLength;
3593
3594 let len = 76;
3595 b.bytes = len as u64;
3596
3597 let mut head = MessageHead::default();
3598 let mut vec = Vec::with_capacity(128);
3599
3600 b.iter(|| {
3601 Server::encode(
3602 Encode {
3603 head: &mut head,
3604 body: Some(BodyLength::Known(10)),
3605 keep_alive: true,
3606 req_method: &mut Some(Method::GET),
3607 title_case_headers: false,
3608 date_header: true,
3609 },
3610 &mut vec,
3611 )
3612 .unwrap();
3613 assert_eq!(vec.len(), len);
3614 ::test::black_box(&vec);
3615
3616 vec.clear();
3617 })
3618 }
3619}