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