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