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