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