1use std::{cell::Cell, fmt, task::Poll};
2
3use ntex_http::header::{HeaderName, HeaderValue};
4use ntex_http::{Method, StatusCode, Version, header};
5use ntex_httparse::{self as httparse, HeaderParsed, Status};
6use urly::Url;
7
8use super::encoder::is_bodyless;
9use crate::http::config::HttpServiceConfig;
10use crate::http::helpers::is_valid_target;
11use crate::http::message::{ConnectionType, ResponseHead};
12use crate::http::{HeaderItem, error::DecodeError, header::HeaderMap, request::Request};
13use crate::util::{ByteString, Bytes, BytesMut};
14use crate::{codec::Decoder, service::cfg::Cfg};
15
16pub(crate) struct MessageDecoder<T: MessageType> {
18 hdrs: Cell<bool>,
19 inner: Cell<Option<Box<Inner<T>>>>,
20}
21
22struct Inner<T: MessageType> {
23 st: State,
24 val: Option<T>,
25 hdr: httparse::Header,
26 hdr_st: httparse::State,
27 cfg: Cfg<HttpServiceConfig>,
28 consumed: usize,
29 headers: u16,
31 line: T::Parser,
33 line_st: httparse::State,
34}
35
36#[derive(Debug, PartialEq, Eq)]
37pub enum PayloadType {
39 None,
41 Payload(PayloadDecoder),
47 Stream(PayloadDecoder),
51}
52
53impl<T: MessageType> Default for MessageDecoder<T> {
54 fn default() -> Self {
55 MessageDecoder::new(Cfg::default())
56 }
57}
58
59impl<T: MessageType> MessageDecoder<T> {
60 pub(crate) fn new(cfg: Cfg<HttpServiceConfig>) -> Self {
61 MessageDecoder {
62 hdrs: Cell::new(false),
63 inner: Cell::new(Some(Box::new(Inner {
64 cfg,
65 st: State::default(),
66 val: None,
67 hdr: httparse::Header::default(),
68 hdr_st: httparse::State::default(),
69 consumed: 0,
70 headers: 0,
71 line: T::Parser::default(),
72 line_st: httparse::State::default(),
73 }))),
74 }
75 }
76
77 pub(super) fn is_reading_hdrs(&self) -> bool {
78 self.hdrs.get()
79 }
80}
81
82impl<T: MessageType> Clone for MessageDecoder<T> {
83 fn clone(&self) -> Self {
84 let inner = self.inner.take().unwrap();
85 let val = MessageDecoder {
86 hdrs: Cell::new(false),
87 inner: Cell::new(Some(Box::new(Inner {
88 st: State::default(),
89 val: None,
90 consumed: 0,
91 headers: 0,
92 line: T::Parser::default(),
93 line_st: httparse::State::default(),
94 hdr: httparse::Header::default(),
95 hdr_st: httparse::State::default(),
96 cfg: inner.cfg.clone(),
97 }))),
98 };
99 self.inner.set(Some(inner));
100 val
101 }
102}
103
104impl<T: MessageType> MessageDecoder<T> {
105 fn decode_headers(src: &mut BytesMut, inner: &mut Inner<T>) -> Poll<Result<(), DecodeError>> {
106 loop {
107 let result = match inner.hdr.parse_with_state(src, &mut inner.hdr_st)? {
108 Status::Complete(result) => result,
109 Status::Partial => return Poll::Pending,
110 };
111 match result {
112 HeaderParsed::Header(len) => {
113 if inner.headers >= inner.cfg.max_headers {
115 return Poll::Ready(Err(DecodeError::MaxHeaders));
116 }
117 inner.headers += 1;
118 let (n, v) = (inner.hdr.name, inner.hdr.value);
119 let Ok(name) = HeaderName::from_bytes(&src[n.start..n.end]) else {
121 return Poll::Ready(Err(DecodeError::Header));
122 };
123
124 let mut pos = 0;
128 let origin = if inner.cfg.headers_vec {
129 src.advance_to(n.start);
130 pos = n.end;
131 Some(src.split_to(n.end - n.start))
132 } else {
133 None
134 };
135 let value = if v.start == v.end {
136 Bytes::new()
137 } else {
138 src.advance_to(v.start - pos);
139 pos = v.end;
140 src.split_to(v.end - v.start)
141 };
142 src.advance_to(len - pos);
143
144 let value = unsafe { HeaderValue::from_shared_unchecked(value) };
146
147 if let Some(origin) = origin {
148 let origin = unsafe { ByteString::from_bytes_unchecked(origin) };
150 inner.val.as_mut().unwrap().set_headers_item(HeaderItem {
151 origin,
152 name: name.clone(),
153 value: value.clone(),
154 });
155 }
156
157 inner.hdr_st = httparse::State::default();
158 inner
159 .val
160 .as_mut()
161 .unwrap()
162 .set_header(&mut inner.st, name, value)?;
163 }
164 HeaderParsed::Eof(len) => {
165 src.advance_to(len);
166 inner.hdr_st = httparse::State::default();
167 break;
168 }
169 }
170 }
171 Poll::Ready(Ok(()))
172 }
173}
174
175impl<T: MessageType> Decoder for MessageDecoder<T> {
176 type Item = (T, PayloadType);
177 type Error = DecodeError;
178
179 fn decode(&self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
180 let mut inner = self.inner.take().unwrap();
181 let result = self.decode_message(src, &mut inner);
182 if result.is_err() {
183 inner.val = None;
185 inner.st = State::default();
186 inner.hdr_st = httparse::State::default();
187 inner.consumed = 0;
188 inner.headers = 0;
189 inner.line_st = httparse::State::default();
190 self.hdrs.set(false);
191 }
192 self.inner.set(Some(inner));
193 result
194 }
195}
196
197impl<T: MessageType> MessageDecoder<T> {
198 fn decode_message(
199 &self,
200 src: &mut BytesMut,
201 inner: &mut Inner<T>,
202 ) -> Result<Option<(T, PayloadType)>, DecodeError> {
203 if !src.is_empty() {
204 self.hdrs.set(true);
205 }
206
207 if inner.val.is_none() && inner.line_st == httparse::State::default() {
211 let skip = empty_lines(src);
212 if skip > 0 {
213 src.advance_to(skip);
214 inner.consumed += skip;
215 }
216 }
217 let len = src.len();
218 let max_line = inner.cfg.max_start_line_size;
219 if inner.val.is_none() {
220 match T::decode(src, &mut inner.line, &mut inner.line_st)? {
223 Poll::Ready(_) if len - src.len() > max_line => {
224 return Err(DecodeError::StartLineTooLong(len - src.len()));
225 }
226 Poll::Ready(val) => {
227 inner.line_st = httparse::State::default();
228 inner.st.version = val.msg_version();
229 inner.st.validate_host = T::REQUEST && inner.cfg.validate_host;
230 inner.val = Some(val);
231 }
232 Poll::Pending => {}
233 }
234 }
235 if inner.val.is_none() && len > max_line {
236 return Err(DecodeError::StartLineTooLong(len));
237 }
238
239 let (result, buf_size) = if inner.val.is_some() {
240 match MessageDecoder::<T>::decode_headers(src, inner) {
241 Poll::Ready(Ok(())) => {
242 let mut val = inner.val.take().unwrap();
243 if T::REQUEST {
244 inner.st.check_upgrade();
245 }
246 let pl_len = inner.st.payload_length();
247 let pl = val.set_payload_length(&mut inner.st, pl_len)?;
248 let consumed = inner.consumed + len - src.len();
249 inner.st = State::default();
250 inner.consumed = 0;
251 inner.headers = 0;
252 self.hdrs.set(false);
253 (Ok(Some((val, pl))), consumed)
254 }
255 Poll::Pending => {
256 let buf_size = inner.consumed + len;
257 inner.consumed = buf_size - src.len();
258 (Ok(None), buf_size)
259 }
260 Poll::Ready(Err(e)) => (Err(e), 0),
261 }
262 } else {
263 (Ok(None), inner.consumed + len)
264 };
265
266 if buf_size > inner.cfg.max_buf_size {
267 log::trace!("MAX_BUFFER_SIZE of data reached, closing");
268 return Err(DecodeError::TooLarge(buf_size));
269 }
270 result
271 }
272}
273
274impl<T: MessageType> fmt::Debug for MessageDecoder<T> {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 f.debug_struct("MessageDecoder").finish()
277 }
278}
279
280#[derive(Debug, PartialEq, Eq)]
281pub(crate) enum PayloadLength {
282 Payload(PayloadType),
283 Upgrade,
284 None,
285}
286
287#[allow(clippy::declare_interior_mutable_const)]
288const ZERO: PayloadLength = PayloadLength::Payload(PayloadType::Payload(PayloadDecoder {
289 kind: Cell::new(Kind::Length(0)),
290}));
291
292impl PayloadLength {
293 fn is_none(&self) -> bool {
295 matches!(self, Self::None)
296 }
297
298 #[allow(clippy::borrow_interior_mutable_const)]
299 fn is_zero(&self) -> bool {
301 self == &ZERO
302 }
303}
304
305bitflags::bitflags! {
306 #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
307 struct Flags: u16 {
308 const HAS_UPGRADE = 0b0001;
309 const EXPECT = 0b0010;
310 const CHUNKED = 0b0100;
311 const SEEN_TE = 0b1000;
312 const CONN_CLOSE = 0b0001_0000;
313 const CONN_KA = 0b0010_0000;
314 const CONN_UPGRADE = 0b0100_0000;
315 const WS_UPGRADE = 0b1000_0000;
316 const SEEN_HOST = 0b0001_0000_0000;
317 const TE_OTHER = 0b0010_0000_0000;
318 }
319}
320
321#[derive(Default, Debug)]
322pub(crate) struct State {
323 flags: Flags,
324 content_length: Option<u64>,
325 version: Version,
326 validate_host: bool,
327}
328
329impl State {
330 fn connection_types(&self) -> impl Iterator<Item = ConnectionType> {
331 [
332 (Flags::CONN_CLOSE, ConnectionType::Close),
333 (Flags::CONN_KA, ConnectionType::KeepAlive),
334 (Flags::CONN_UPGRADE, ConnectionType::Upgrade),
335 ]
336 .into_iter()
337 .filter_map(|(flag, ctype)| self.flags.contains(flag).then_some(ctype))
338 }
339
340 fn check_upgrade(&mut self) {
343 if !self
344 .flags
345 .contains(Flags::HAS_UPGRADE | Flags::CONN_UPGRADE)
346 {
347 self.flags
348 .remove(Flags::HAS_UPGRADE | Flags::WS_UPGRADE | Flags::CONN_UPGRADE);
349 }
350 }
351
352 fn payload_length(&self) -> PayloadLength {
353 if self.flags.contains(Flags::CHUNKED) {
355 PayloadLength::Payload(PayloadType::Payload(PayloadDecoder::chunked()))
357 } else if let Some(len) = self.content_length
358 && !(len == 0 && self.flags.contains(Flags::WS_UPGRADE))
360 {
361 PayloadLength::Payload(PayloadType::Payload(PayloadDecoder::length(len)))
363 } else if self.flags.contains(Flags::HAS_UPGRADE) {
364 PayloadLength::Upgrade
365 } else {
366 PayloadLength::None
367 }
368 }
369}
370
371pub(crate) trait MessageType: fmt::Debug + Sized {
372 const REQUEST: bool;
374
375 type Parser: Default;
377
378 fn msg_version(&self) -> Version;
379
380 fn ignore_http11_features(st: &State) -> bool {
384 Self::REQUEST && st.version < Version::HTTP_11
385 }
386
387 fn headers_mut(&mut self) -> &mut HeaderMap;
388
389 fn decode(
392 src: &mut BytesMut,
393 parser: &mut Self::Parser,
394 st: &mut httparse::State,
395 ) -> Result<Poll<Self>, DecodeError>;
396
397 fn set_payload_length(
398 &mut self,
399 st: &mut State,
400 length: PayloadLength,
401 ) -> Result<PayloadType, DecodeError>;
402
403 fn set_headers_item(&mut self, item: HeaderItem);
404
405 fn set_header(
406 &mut self,
407 st: &mut State,
408 name: HeaderName,
409 value: HeaderValue,
410 ) -> Result<(), DecodeError> {
411 match name {
412 header::CONTENT_LENGTH
413 if st.content_length.is_some()
414 || st.flags.intersects(Flags::CHUNKED | Flags::TE_OTHER) =>
415 {
416 log::trace!("multiple Content-Length or Transfer-Encoding with Content-Length");
417 return Err(DecodeError::Header);
418 }
419 header::CONTENT_LENGTH => match value.to_str() {
420 Ok(s) if s.trim_start().starts_with('+') => {
421 log::trace!("illegal Content-Length: {s:?}");
422 return Err(DecodeError::Header);
423 }
424 Ok(s) => {
425 if let Ok(len) = atoi_simd::parse::<u64, true, true>(s.as_bytes()) {
426 st.content_length = Some(len);
429 } else {
430 log::trace!("illegal Content-Length: {s:?}");
431 return Err(DecodeError::Header);
432 }
433 }
434 Err(_) => {
435 log::trace!("illegal Content-Length: {value:?}");
436 return Err(DecodeError::Header);
437 }
438 },
439 header::TRANSFER_ENCODING if st.flags.contains(Flags::SEEN_TE) => {
441 log::trace!("Transfer-Encoding header usage is not allowed");
442 return Err(DecodeError::Header);
443 }
444 header::TRANSFER_ENCODING if st.version == Version::HTTP_11 => {
445 st.flags.insert(Flags::SEEN_TE);
446 let Some((chunked, other)) = transfer_codings(value.as_bytes()) else {
447 log::trace!("illegal Transfer-Encoding: {value:?}");
448 return Err(DecodeError::Header);
449 };
450 if st.content_length.is_some() && (chunked || other) {
451 log::trace!("Transfer-Encoding with Content-Length not allowed");
452 return Err(DecodeError::Header);
453 }
454 if chunked {
455 st.flags.insert(Flags::CHUNKED);
456 } else if other {
457 st.flags.insert(Flags::TE_OTHER);
460 }
461 if Self::REQUEST {
462 if !chunked {
463 log::trace!("request without final chunked coding: {value:?}");
464 return Err(DecodeError::Header);
465 }
466 if other {
467 log::trace!("unsupported transfer coding: {value:?}");
468 return Err(DecodeError::UnsupportedTransferCoding);
469 }
470 }
471 }
472 header::TRANSFER_ENCODING if st.version == Version::HTTP_10 => {
473 return Err(DecodeError::InvalidInput(
474 "Transfer-Encoding is not supported by HTTP/1.0",
475 ));
476 }
477 header::CONNECTION => {
479 let mut flags = connection_flags(value.as_bytes());
480 if Self::ignore_http11_features(st) {
481 flags.remove(Flags::CONN_UPGRADE);
482 }
483 st.flags.insert(flags);
484 }
485 header::HOST if st.validate_host => {
487 if st.flags.contains(Flags::SEEN_HOST) {
488 log::trace!("multiple Host headers not allowed");
489 return Err(DecodeError::Header);
490 }
491 let host = value.to_str().map(urly::Authority::new);
493 if !matches!(host, Ok(Ok(host)) if host.userinfo().is_none()) {
494 log::trace!("illegal Host: {value:?}");
495 return Err(DecodeError::Header);
496 }
497 st.flags.insert(Flags::SEEN_HOST);
498 }
499 header::UPGRADE | header::EXPECT if Self::ignore_http11_features(st) => (),
500 header::UPGRADE => {
501 st.flags.insert(Flags::HAS_UPGRADE);
502 if value
503 .as_bytes()
504 .trim_ascii()
505 .eq_ignore_ascii_case(b"websocket")
506 {
507 st.flags.insert(Flags::WS_UPGRADE);
508 }
509 }
510 header::EXPECT
513 if value
514 .as_bytes()
515 .split(|&b| b == b',')
516 .any(|e| e.trim_ascii().eq_ignore_ascii_case(b"100-continue")) =>
517 {
518 st.flags.insert(Flags::EXPECT);
519 }
520 _ => (),
521 }
522
523 self.headers_mut().append(name, value);
524 Ok(())
525 }
526}
527
528impl MessageType for Request {
529 const REQUEST: bool = true;
530
531 type Parser = httparse::Request;
532
533 fn msg_version(&self) -> Version {
534 self.version()
535 }
536
537 fn headers_mut(&mut self) -> &mut HeaderMap {
538 &mut self.head_mut().headers
539 }
540
541 fn decode(
542 src: &mut BytesMut,
543 req: &mut httparse::Request,
544 st: &mut httparse::State,
545 ) -> Result<Poll<Self>, DecodeError> {
546 match req.parse_with_state(src, st)? {
547 Status::Complete(pos) => {
548 let method = Method::from_bytes(&src[req.method.start..req.method.end])
549 .map_err(|_| DecodeError::Method)?;
550 let target = &src[req.path.start..req.path.end];
551 if !is_valid_target(target) {
552 return Err(DecodeError::Uri);
553 }
554 if target == b"*" && method != Method::OPTIONS {
557 return Err(DecodeError::Uri);
558 }
559 src.advance_to(req.path.start);
562 let target = src.split_to(req.path.end - req.path.start);
563 src.advance_to(pos - req.path.end);
564 let uri = if method == Method::CONNECT {
565 let target = str::from_utf8(&target).map_err(|_| DecodeError::Uri)?;
568 let uri = Url::parse(target)?;
569 if uri.authority().is_some_and(|a| a.userinfo().is_some()) {
570 return Err(DecodeError::Uri);
571 }
572 uri
573 } else {
574 let asterisk = &target[..] == b"*";
576 let uri = if target.starts_with(b"//") {
577 let target = str::from_utf8(&target).map_err(|_| DecodeError::Uri)?;
579 Url::try_from(format!("/.{target}"))?
580 } else {
581 let target = unsafe { ByteString::from_bytes_unchecked(target) };
583 Url::try_from(target)?
585 };
586 let valid = if uri.is_absolute() {
587 uri.host().is_some()
589 && uri.authority().is_some_and(|a| a.userinfo().is_none())
590 } else {
591 uri.authority().is_none()
592 && (uri.path().as_str().starts_with('/') || asterisk)
593 };
594 if !valid {
595 return Err(DecodeError::Uri);
596 }
597 uri
598 };
599 let version = if req.version == 1 {
600 Version::HTTP_11
601 } else {
602 Version::HTTP_10
603 };
604
605 let mut msg = Request::new();
606 let head = msg.head_mut();
607 head.uri = uri;
608 head.method = method;
609 head.version = version;
610 Ok(Poll::Ready(msg))
611 }
612 Status::Partial => Ok(Poll::Pending),
613 }
614 }
615
616 fn set_headers_item(&mut self, item: HeaderItem) {
617 self.head_mut().headers_vec.push(item);
618 }
619
620 fn set_payload_length(
621 &mut self,
622 st: &mut State,
623 mut length: PayloadLength,
624 ) -> Result<PayloadType, DecodeError> {
625 if self.version() == Version::HTTP_10 && self.method() == Method::POST && length.is_none() {
628 log::trace!("no Content-Length specified for HTTP/1.0 POST request");
629 return Err(DecodeError::Header);
630 }
631 if st.validate_host
632 && self.version() >= Version::HTTP_11
633 && !st.flags.contains(Flags::SEEN_HOST)
634 {
635 log::trace!("no Host header specified for HTTP/1.1 request");
636 return Err(DecodeError::Header);
637 }
638
639 for ctype in st.connection_types() {
640 self.head_mut().set_connection_type(ctype);
641 }
642 if st.flags.contains(Flags::EXPECT) {
643 self.head_mut().set_expect();
644 }
645
646 if length.is_zero() {
650 length = PayloadLength::None;
651 }
652
653 let decoder = match length {
655 PayloadLength::Payload(pl) => pl,
656 PayloadLength::Upgrade => {
657 self.head_mut().set_upgrade();
659 PayloadType::Stream(PayloadDecoder::eof())
660 }
661 PayloadLength::None => {
662 if self.method() == Method::CONNECT {
663 self.head_mut().set_upgrade();
664 PayloadType::Stream(PayloadDecoder::eof())
665 } else {
666 PayloadType::None
667 }
668 }
669 };
670
671 Ok(decoder)
672 }
673}
674
675impl MessageType for ResponseHead {
676 const REQUEST: bool = false;
677
678 type Parser = httparse::Response;
679
680 fn msg_version(&self) -> Version {
681 self.version
682 }
683
684 fn headers_mut(&mut self) -> &mut HeaderMap {
685 &mut self.headers
686 }
687
688 fn decode(
689 src: &mut BytesMut,
690 res: &mut httparse::Response,
691 st: &mut httparse::State,
692 ) -> Result<Poll<Self>, DecodeError> {
693 match res.parse_with_state(src, st)? {
694 Status::Complete(pos) => {
695 let version = if res.version == 1 {
696 Version::HTTP_11
697 } else {
698 Version::HTTP_10
699 };
700 let status = StatusCode::from_u16(res.code).map_err(|_| DecodeError::Status)?;
701
702 src.advance_to(pos);
703 Ok(Poll::Ready(ResponseHead::new(status, version)))
704 }
705 Status::Partial => Ok(Poll::Pending),
706 }
707 }
708
709 fn set_headers_item(&mut self, item: HeaderItem) {
710 self.headers_vec.push(item);
711 }
712
713 fn set_payload_length(
714 &mut self,
715 st: &mut State,
716 length: PayloadLength,
717 ) -> Result<PayloadType, DecodeError> {
718 for ctype in st.connection_types() {
719 self.set_connection_type(ctype);
720 }
721
722 if is_bodyless(self.status) {
725 return Ok(PayloadType::None);
726 }
727
728 let decoder = if self.status == StatusCode::SWITCHING_PROTOCOLS
730 && (length.is_zero() || !matches!(length, PayloadLength::Payload(_)))
731 {
732 PayloadType::Stream(PayloadDecoder::eof())
734 } else if length.is_zero() {
735 PayloadType::None
736 } else if let PayloadLength::Payload(pl) = length {
737 pl
738 } else {
739 self.set_connection_type(ConnectionType::Close);
742 PayloadType::Payload(PayloadDecoder::eof())
743 };
744
745 Ok(decoder)
746 }
747}
748
749fn transfer_codings(val: &[u8]) -> Option<(bool, bool)> {
756 let mut chunked = false;
757 let mut seen_chunked = false;
758 let mut other = false;
759 for coding in val.split(|&b| b == b',').map(<[u8]>::trim_ascii) {
761 if coding.is_empty() {
762 continue;
763 }
764 let name = coding.split(|&b| b == b';').next().unwrap_or_default();
765 let name = name.trim_ascii();
766 if name.is_empty() || !name.iter().copied().all(is_tchar) {
767 return None;
768 }
769 if name.eq_ignore_ascii_case(b"chunked") {
770 if seen_chunked || name.len() != coding.len() {
772 return None;
773 }
774 chunked = true;
775 seen_chunked = true;
776 } else if chunked {
777 chunked = false;
779 other = true;
780 } else if !name.eq_ignore_ascii_case(b"identity") {
781 other = true;
782 }
783 }
784 Some((chunked, other))
785}
786
787fn connection_flags(val: &[u8]) -> Flags {
788 let mut flags = Flags::empty();
789 for token in val.split(|&b| b == b',') {
790 let token = token.trim_ascii();
791 if token.eq_ignore_ascii_case(b"close") {
792 flags.insert(Flags::CONN_CLOSE);
793 } else if token.eq_ignore_ascii_case(b"keep-alive") {
794 flags.insert(Flags::CONN_KA);
795 } else if token.eq_ignore_ascii_case(b"upgrade") {
796 flags.insert(Flags::CONN_UPGRADE);
797 }
798 }
799 flags
800}
801
802#[derive(Debug, Clone, PartialEq, Eq)]
803pub enum PayloadItem {
805 Chunk(Bytes),
807 Trailers(HeaderMap),
809 Eof,
811}
812
813#[derive(Debug, Clone, PartialEq, Eq)]
836pub struct PayloadDecoder {
837 kind: Cell<Kind>,
838}
839
840impl PayloadDecoder {
841 pub(super) fn length(x: u64) -> PayloadDecoder {
842 PayloadDecoder {
843 kind: Cell::new(Kind::Length(x)),
844 }
845 }
846
847 pub(super) fn chunked() -> PayloadDecoder {
848 let limits = ChunkedLimits {
849 ext: 0,
850 trailers: 0,
851 line: 0,
852 line_state: SizeLine::Unknown,
853 };
854 PayloadDecoder {
855 kind: Cell::new(Kind::Chunked(ChunkedState::Size, 0, limits)),
856 }
857 }
858
859 pub(crate) fn eof() -> PayloadDecoder {
860 PayloadDecoder {
861 kind: Cell::new(Kind::Eof),
862 }
863 }
864
865 pub(crate) fn is_eof(&self) -> bool {
867 self.kind.get() == Kind::Eof
868 }
869}
870
871#[derive(Debug, Copy, Clone, PartialEq, Eq)]
872enum Kind {
873 Length(u64),
876 Chunked(ChunkedState, u64, ChunkedLimits),
881 Eof,
896}
897
898const MAX_CHUNK_EXTENSIONS: u32 = 16 * 1024;
901
902const MAX_CHUNK_TRAILERS: u32 = 4 * 1024;
905
906const SMALL_CHUNK: usize = 1024;
908
909const MAX_MERGED_CHUNKS: usize = 16 * 1024;
911
912#[derive(Debug, Copy, Clone, PartialEq, Eq)]
913struct ChunkedLimits {
914 ext: u32,
916 trailers: u32,
918 line: u32,
920 line_state: SizeLine,
922}
923
924#[derive(Debug, Copy, Clone, PartialEq, Eq)]
926enum SizeLine {
927 Unknown,
929 Lws,
931 Ext,
933}
934
935impl SizeLine {
936 fn is_neutral(self, bytes: &[u8]) -> bool {
938 match self {
939 SizeLine::Unknown => false,
940 SizeLine::Lws => bytes.iter().all(|&b| b == b' ' || b == b'\t'),
941 SizeLine::Ext => bytes
943 .iter()
944 .all(|&b| b == b'\t' || (b >= 0x20 && b != 0x7f)),
945 }
946 }
947}
948
949#[derive(Debug, PartialEq, Eq, Copy, Clone)]
950enum ChunkedState {
951 Size,
952 Body,
953 BodyCr,
954 BodyLf,
955 EndCr,
956 EndLf,
957 Trailers,
958 End,
959}
960
961impl Decoder for PayloadDecoder {
962 type Item = PayloadItem;
963 type Error = DecodeError;
964
965 fn decode(&self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
966 let mut kind = self.kind.get();
967
968 match kind {
969 Kind::Length(ref mut remaining) => {
970 if *remaining == 0 {
971 Ok(Some(PayloadItem::Eof))
972 } else {
973 if src.is_empty() {
974 return Ok(None);
975 }
976 let len = src.len() as u64;
977 let buf;
978 if *remaining > len {
979 buf = src.take();
980 *remaining -= len;
981 } else {
982 buf = src.split_to(*remaining as usize);
983 *remaining = 0;
984 }
985 self.kind.set(kind);
986 log::trace!("Length read: {}", buf.len());
987 Ok(Some(PayloadItem::Chunk(buf)))
988 }
989 }
990 Kind::Chunked(ref mut state, ref mut size, ref mut limits) => {
991 let mut data: Option<Bytes> = None;
994 let mut merged: Option<BytesMut> = None;
995 let mut trailers: Option<HeaderMap> = None;
996 let result = loop {
997 if *state == ChunkedState::Body && *size >= SMALL_CHUNK as u64 && data.is_some()
999 {
1000 break Ok(None);
1001 }
1002 if *state == ChunkedState::Trailers && data.is_some() {
1004 break Ok(None);
1005 }
1006
1007 let mut buf = None;
1008 *state = match state.step(src, size, limits, &mut buf, &mut trailers) {
1010 Poll::Pending => break Ok(None),
1011 Poll::Ready(Ok(state)) => state,
1012 Poll::Ready(Err(e)) => break Err(e),
1013 };
1014
1015 if *state == ChunkedState::End {
1016 log::trace!("End of chunked stream");
1017 break Ok(Some(
1018 trailers
1019 .take()
1020 .map_or(PayloadItem::Eof, PayloadItem::Trailers),
1021 ));
1022 }
1023
1024 if let Some(buf) = buf {
1025 let len = if let Some(first) = &data {
1026 let m = merged.get_or_insert_with(|| {
1027 let cap = first.len() + buf.len() + src.len();
1028 let mut m = BytesMut::with_capacity(cap.min(MAX_MERGED_CHUNKS));
1029 m.extend_from_slice(first);
1030 m
1031 });
1032 m.extend_from_slice(&buf);
1033 m.len()
1034 } else {
1035 let len = buf.len();
1036 data = Some(buf);
1037 len
1038 };
1039 if len >= SMALL_CHUNK && (merged.is_none() || len >= MAX_MERGED_CHUNKS) {
1040 break Ok(None);
1041 }
1042 }
1043 if src.is_empty() {
1044 break Ok(None);
1045 }
1046 };
1047 self.kind.set(kind);
1048
1049 match result {
1051 Ok(_) if data.is_some() => {
1052 let data = merged.map_or_else(|| data.unwrap(), BytesMut::freeze);
1053 Ok(Some(PayloadItem::Chunk(data)))
1054 }
1055 result => result,
1056 }
1057 }
1058 Kind::Eof => {
1059 if src.is_empty() {
1060 Ok(None)
1061 } else {
1062 Ok(Some(PayloadItem::Chunk(src.take())))
1063 }
1064 }
1065 }
1066 }
1067}
1068
1069macro_rules! byte (
1070 ($rdr:ident) => ({
1071 if $rdr.len() > 0 {
1072 let b = $rdr[0];
1073 $rdr.advance_to(1);
1074 b
1075 } else {
1076 return Poll::Pending
1077 }
1078 })
1079);
1080
1081impl ChunkedState {
1082 fn step(
1083 self,
1084 body: &mut BytesMut,
1085 size: &mut u64,
1086 limits: &mut ChunkedLimits,
1087 buf: &mut Option<Bytes>,
1088 trailers: &mut Option<HeaderMap>,
1089 ) -> Poll<Result<ChunkedState, DecodeError>> {
1090 match self {
1091 ChunkedState::Size => ChunkedState::read_size(body, size, limits),
1092 ChunkedState::Body => ChunkedState::read_body(body, size, buf),
1093 ChunkedState::BodyCr => ChunkedState::read_body_cr(body),
1094 ChunkedState::BodyLf => ChunkedState::read_body_lf(body),
1095 ChunkedState::EndCr => ChunkedState::read_end_cr(body),
1096 ChunkedState::EndLf => ChunkedState::read_end_lf(body),
1097 ChunkedState::Trailers => ChunkedState::read_trailers(body, limits, trailers),
1098 ChunkedState::End => Poll::Ready(Ok(ChunkedState::End)),
1099 }
1100 }
1101
1102 fn read_size(
1108 rdr: &mut BytesMut,
1109 size: &mut u64,
1110 limits: &mut ChunkedLimits,
1111 ) -> Poll<Result<ChunkedState, DecodeError>> {
1112 let max = (MAX_CHUNK_EXTENSIONS - limits.ext) as usize + 18;
1114
1115 let line = limits.line as usize;
1118 if line != 0 && line <= rdr.len() && limits.line_state.is_neutral(&rdr[line..]) {
1119 return if rdr.len() > max {
1120 Poll::Ready(Err(DecodeError::InvalidInput(
1121 "Chunk extensions are too large",
1122 )))
1123 } else {
1124 limits.line = rdr.len() as u32;
1125 Poll::Pending
1126 };
1127 }
1128
1129 match httparse::parse_chunk_size(rdr) {
1130 Ok(httparse::Status::Complete((pos, sz))) => {
1131 limits.line = 0;
1132 limits.line_state = SizeLine::Unknown;
1133
1134 let digits = rdr.iter().take_while(|b| b.is_ascii_hexdigit()).count();
1135 limits.ext = limits.ext.saturating_add((pos - digits - 2) as u32);
1137 if limits.ext > MAX_CHUNK_EXTENSIONS {
1138 return Poll::Ready(Err(DecodeError::InvalidInput(
1139 "Chunk extensions are too large",
1140 )));
1141 }
1142 rdr.advance_to(pos);
1143 *size = sz;
1144 if sz > 0 {
1145 Poll::Ready(Ok(ChunkedState::Body))
1146 } else {
1147 Poll::Ready(Ok(ChunkedState::EndCr))
1148 }
1149 }
1150 Ok(httparse::Status::Partial) => {
1151 if rdr.len() > max {
1152 return Poll::Ready(Err(DecodeError::InvalidInput(
1153 "Chunk extensions are too large",
1154 )));
1155 }
1156 limits.line = rdr.len() as u32;
1157 limits.line_state = if rdr.last() == Some(&b'\r') {
1158 SizeLine::Unknown
1160 } else if rdr.contains(&b';') {
1161 SizeLine::Ext
1162 } else if rdr.iter().any(|&b| b == b' ' || b == b'\t') {
1163 SizeLine::Lws
1164 } else {
1165 SizeLine::Unknown
1166 };
1167 Poll::Pending
1168 }
1169 Err(_) => Poll::Ready(Err(DecodeError::InvalidInput(
1170 "Invalid chunk size line: Invalid Size",
1171 ))),
1172 }
1173 }
1174
1175 fn read_body(
1176 rdr: &mut BytesMut,
1177 rem: &mut u64,
1178 buf: &mut Option<Bytes>,
1179 ) -> Poll<Result<ChunkedState, DecodeError>> {
1180 log::trace!("Chunked read, remaining={rem:?}");
1181
1182 let len = rdr.len() as u64;
1183 if len == 0 {
1184 Poll::Ready(Ok(ChunkedState::Body))
1185 } else {
1186 let slice;
1187 if *rem > len {
1188 slice = rdr.take();
1189 *rem -= len;
1190 } else {
1191 slice = rdr.split_to(*rem as usize);
1192 *rem = 0;
1193 }
1194 *buf = Some(slice);
1195 if *rem > 0 {
1196 Poll::Ready(Ok(ChunkedState::Body))
1197 } else {
1198 Poll::Ready(Ok(ChunkedState::BodyCr))
1199 }
1200 }
1201 }
1202
1203 fn read_body_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, DecodeError>> {
1204 match byte!(rdr) {
1205 b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
1206 _ => Poll::Ready(Err(DecodeError::InvalidInput("Invalid chunk body CR"))),
1207 }
1208 }
1209
1210 fn read_body_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, DecodeError>> {
1211 match byte!(rdr) {
1212 b'\n' => Poll::Ready(Ok(ChunkedState::Size)),
1213 _ => Poll::Ready(Err(DecodeError::InvalidInput("Invalid chunk body LF"))),
1214 }
1215 }
1216
1217 fn read_end_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, DecodeError>> {
1218 match rdr.first() {
1219 None => Poll::Pending,
1220 Some(b'\r') => {
1221 rdr.advance_to(1);
1222 Poll::Ready(Ok(ChunkedState::EndLf))
1223 }
1224 Some(&b) if is_tchar(b) => Poll::Ready(Ok(ChunkedState::Trailers)),
1226 Some(_) => Poll::Ready(Err(DecodeError::InvalidInput("Invalid chunk end CR"))),
1227 }
1228 }
1229
1230 fn read_trailers(
1235 rdr: &mut BytesMut,
1236 limits: &mut ChunkedLimits,
1237 trailers: &mut Option<HeaderMap>,
1238 ) -> Poll<Result<ChunkedState, DecodeError>> {
1239 const TOO_LARGE: DecodeError = DecodeError::InvalidInput("Chunked trailers are too large");
1240 const INVALID: DecodeError = DecodeError::InvalidInput("Invalid chunked trailer field");
1241
1242 let mut pos = limits.trailers as usize;
1243 while pos < rdr.len() {
1244 if rdr[pos] == b'\r' {
1245 return match rdr.get(pos + 1) {
1247 None => break,
1248 Some(b'\n') => {
1249 let section = rdr.split_to(pos + 2);
1250 let mut hdrs = HeaderMap::new();
1251 for line in section[..pos].split(|&b| b == b'\n') {
1252 let Some(line) = line.strip_suffix(b"\r") else {
1253 continue;
1254 };
1255 let (name, value) = trailer_field(line).ok_or(INVALID)?;
1256 hdrs.append(
1257 HeaderName::from_bytes(name).map_err(|_| INVALID)?,
1258 HeaderValue::from_bytes(value).map_err(|_| INVALID)?,
1259 );
1260 }
1261 *trailers = Some(hdrs);
1262 Poll::Ready(Ok(ChunkedState::End))
1263 }
1264 Some(_) => Poll::Ready(Err(DecodeError::InvalidInput("Invalid chunk end LF"))),
1265 };
1266 }
1267 if !is_tchar(rdr[pos]) {
1268 return Poll::Ready(Err(INVALID));
1269 }
1270
1271 let Some(end) = rdr[pos..].iter().position(|&b| b == b'\r') else {
1273 break;
1274 };
1275 if trailer_field(&rdr[pos..pos + end]).is_none() {
1276 return Poll::Ready(Err(INVALID));
1277 }
1278 match rdr.get(pos + end + 1) {
1279 None => break,
1280 Some(b'\n') => {
1281 pos += end + 2;
1282 if pos > MAX_CHUNK_TRAILERS as usize {
1283 return Poll::Ready(Err(TOO_LARGE));
1284 }
1285 }
1286 Some(_) => {
1287 return Poll::Ready(Err(DecodeError::InvalidInput(
1288 "Invalid chunked trailer field LF",
1289 )));
1290 }
1291 }
1292 }
1293 limits.trailers = pos as u32;
1294
1295 if rdr.len() > MAX_CHUNK_TRAILERS as usize && rdr.get(pos) != Some(&b'\r') {
1297 Poll::Ready(Err(TOO_LARGE))
1298 } else {
1299 Poll::Pending
1300 }
1301 }
1302
1303 fn read_end_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, DecodeError>> {
1304 match byte!(rdr) {
1305 b'\n' => Poll::Ready(Ok(ChunkedState::End)),
1306 _ => Poll::Ready(Err(DecodeError::InvalidInput("Invalid chunk end LF"))),
1307 }
1308 }
1309}
1310
1311fn empty_lines(buf: &[u8]) -> usize {
1313 let mut pos = 0;
1314 loop {
1315 match &buf[pos..] {
1316 [b'\n', ..] => pos += 1,
1317 [b'\r', b'\n', ..] => pos += 2,
1318 _ => return pos,
1319 }
1320 }
1321}
1322
1323fn trailer_field(line: &[u8]) -> Option<(&[u8], &[u8])> {
1325 let colon = line.iter().position(|&b| b == b':')?;
1326 let (name, value) = (&line[..colon], &line[colon + 1..]);
1327 let valid = !name.is_empty()
1328 && name.iter().all(|&b| is_tchar(b))
1329 && value
1330 .iter()
1331 .all(|&b| b == b'\t' || (b' '..=b'~').contains(&b) || b >= 0x80);
1332 valid.then(|| (name, value.trim_ascii()))
1333}
1334
1335fn is_tchar(b: u8) -> bool {
1337 b.is_ascii_alphanumeric() || b"!#$%&'*+-.^_`|~".contains(&b)
1338}
1339
1340#[cfg(test)]
1341mod tests {
1342 use super::*;
1343 use crate::http::{HttpMessage, header, header::SET_COOKIE};
1344 use crate::service::cfg::SharedCfg;
1345
1346 impl PayloadType {
1347 fn unwrap(self) -> PayloadDecoder {
1348 if let PayloadType::Payload(pl) = self {
1349 pl
1350 } else {
1351 panic!()
1352 }
1353 }
1354
1355 fn is_unhandled(&self) -> bool {
1356 matches!(self, PayloadType::Stream(_))
1357 }
1358 }
1359
1360 impl PayloadItem {
1361 fn chunk(self) -> Bytes {
1362 match self {
1363 PayloadItem::Chunk(chunk) => chunk,
1364 PayloadItem::Trailers(_) | PayloadItem::Eof => panic!("error"),
1365 }
1366 }
1367 fn eof(&self) -> bool {
1368 matches!(*self, PayloadItem::Eof)
1369 }
1370 }
1371
1372 macro_rules! parse_ready {
1373 ($e:expr) => {{
1374 match MessageDecoder::<Request>::default().decode($e) {
1375 Ok(Some((msg, _))) => msg,
1376 Ok(_) => unreachable!("Eof during parsing http request"),
1377 Err(err) => unreachable!("Error during parsing http request: {:?}", err),
1378 }
1379 }};
1380 }
1381
1382 macro_rules! expect_parse_err {
1383 ($e:expr) => {{
1384 match MessageDecoder::<Request>::default().decode($e) {
1385 Err(_) => (),
1386 _ => unreachable!("Error expected"),
1387 }
1388 }};
1389 }
1390
1391 #[test]
1392 fn test_asterisk_form_only_for_options() {
1394 let mut buf = BytesMut::from("OPTIONS * HTTP/1.1\r\nhost: a\r\n\r\n");
1395 let req = parse_ready!(&mut buf);
1396 assert_eq!(req.path(), "*");
1397
1398 for method in ["GET", "POST", "HEAD", "CONNECT"] {
1399 let mut buf =
1400 BytesMut::from(format!("{method} * HTTP/1.1\r\nhost: a\r\n\r\n").as_str());
1401 match MessageDecoder::<Request>::default().decode(&mut buf) {
1402 Err(DecodeError::Uri) => (),
1403 res => panic!("{method}: {res:?}"),
1404 }
1405 }
1406 }
1407
1408 #[test]
1409 fn test_authority_form_only_for_connect() {
1410 let mut buf = BytesMut::from("CONNECT example.com:443 HTTP/1.1\r\nhost: a\r\n\r\n");
1411 let req = parse_ready!(&mut buf);
1412 assert_eq!(req.uri().authority().unwrap(), "example.com:443");
1413
1414 let mut buf = BytesMut::from("GET http://example.com/ HTTP/1.1\r\nhost: a\r\n\r\n");
1415 let req = parse_ready!(&mut buf);
1416 assert_eq!(req.path(), "/");
1417
1418 let mut buf = BytesMut::from("GET http://[email protected]/ HTTP/1.1\r\nhost: a\r\n\r\n");
1420 match MessageDecoder::<Request>::default().decode(&mut buf) {
1421 Err(DecodeError::Uri) => (),
1422 res => panic!("{res:?}"),
1423 }
1424
1425 for method in ["GET", "POST", "HEAD", "OPTIONS"] {
1426 let mut buf = BytesMut::from(
1427 format!("{method} example.com:443 HTTP/1.1\r\nhost: a\r\n\r\n").as_str(),
1428 );
1429 match MessageDecoder::<Request>::default().decode(&mut buf) {
1430 Err(DecodeError::Uri) => (),
1431 res => panic!("{method}: {res:?}"),
1432 }
1433 }
1434
1435 let mut buf = BytesMut::from("CONNECT [::1]:443 HTTP/1.1\r\nhost: a\r\n\r\n");
1436 let req = parse_ready!(&mut buf);
1437 assert_eq!(req.uri().authority().unwrap(), "[::1]:443");
1438
1439 for target in [
1440 "/",
1441 "/test",
1442 "http://example.com:443/",
1443 "u@h:1",
1444 ":443",
1445 "h:1?q",
1446 ] {
1447 let mut buf =
1448 BytesMut::from(format!("CONNECT {target} HTTP/1.1\r\nhost: a\r\n\r\n").as_str());
1449 match MessageDecoder::<Request>::default().decode(&mut buf) {
1450 Err(DecodeError::Uri) => (),
1451 res => panic!("{target}: {res:?}"),
1452 }
1453 }
1454 }
1455
1456 #[test]
1457 fn test_request_target() {
1458 for (target, path_and_query) in [
1459 ("/a/../b", "/b"),
1460 ("/a/%2e%2E/b", "/b"),
1461 ("/%7e%3b%2f?%7E%3d", "/~;%2F?~%3D"),
1462 (
1463 "/a[0]|^`{}?a[]=1&b=%00",
1464 "/a%5B0%5D%7C%5E%60%7B%7D?a%5B%5D=1&b=%00",
1465 ),
1466 ("//a//b?c", "//a//b?c"),
1467 ("http://example.com//a", "//a"),
1468 ] {
1469 let mut buf =
1470 BytesMut::from(format!("GET {target} HTTP/1.1\r\nhost: a\r\n\r\n").as_str());
1471 let req = parse_ready!(&mut buf);
1472 assert_eq!(req.uri().path_and_query(), path_and_query, "{target}");
1473 }
1474
1475 for target in [
1476 "http:///x",
1477 "a/b",
1478 "http://[::1/",
1479 "/a#frag",
1480 "/a?b=c#frag",
1481 "/a%zz",
1482 "/a%",
1483 "/a\"",
1484 "/a<b>",
1485 "/a\\b",
1486 "/\u{fc}",
1487 "/a%00b",
1488 "http://example.com/%00",
1489 ] {
1490 let mut buf =
1491 BytesMut::from(format!("GET {target} HTTP/1.1\r\nhost: a\r\n\r\n").as_str());
1492 match MessageDecoder::<Request>::default().decode(&mut buf) {
1493 Err(DecodeError::Uri) => (),
1494 res => panic!("{target}: {res:?}"),
1495 }
1496 }
1497 }
1498
1499 #[test]
1500 fn test_too_long_header_name() {
1501 let mut buf = BytesMut::from("GET / HTTP/1.1\r\n");
1502 let reader = MessageDecoder::<Request>::default();
1503 assert!(reader.decode(&mut buf).unwrap().is_none());
1504
1505 buf.extend_from_slice("a".repeat(64 * 1024 - 16).as_bytes());
1507 assert!(reader.decode(&mut buf).unwrap().is_none());
1508
1509 buf.extend_from_slice(b"aaaaaaaaaaaaaaaaaaaa: v\r\n\r\n");
1510 assert!(matches!(reader.decode(&mut buf), Err(DecodeError::Header)));
1511 }
1512
1513 #[test]
1514 fn test_partial_start_line_is_resumed() {
1515 let reader = MessageDecoder::<Request>::default();
1516 let mut buf = BytesMut::from("GET /");
1517 assert!(reader.decode(&mut buf).unwrap().is_none());
1518
1519 buf.extend_from_slice(b"\x01");
1521 assert!(reader.decode(&mut buf).is_err());
1522
1523 let mut buf = BytesMut::from("GET /a HTTP/1.1\r\nhost: a\r\n\r\n");
1525 assert_eq!(reader.decode(&mut buf).unwrap().unwrap().0.path(), "/a");
1526
1527 let reader = MessageDecoder::<Request>::default();
1529 let mut buf = BytesMut::new();
1530 for b in b"\r\nGET /test/path HTTP/1.1\r\nhost: a\r\n\r" {
1531 buf.extend_from_slice(&[*b]);
1532 assert!(reader.decode(&mut buf).unwrap().is_none());
1533 }
1534 buf.extend_from_slice(b"\n");
1535 let req = reader.decode(&mut buf).unwrap().unwrap().0;
1536 assert_eq!(req.path(), "/test/path");
1537 assert_eq!(req.headers().get("host").unwrap(), "a");
1538
1539 let reader = MessageDecoder::<ResponseHead>::default();
1540 let mut buf = BytesMut::new();
1541 for b in b"HTTP/1.1 404 Not Found\r\n\r" {
1542 buf.extend_from_slice(&[*b]);
1543 assert!(reader.decode(&mut buf).unwrap().is_none());
1544 }
1545 buf.extend_from_slice(b"\n");
1546 let res = reader.decode(&mut buf).unwrap().unwrap().0;
1547 assert_eq!(res.status, StatusCode::NOT_FOUND);
1548
1549 let r1 = MessageDecoder::<Request>::default();
1551 let r2 = MessageDecoder::<Request>::default();
1552 let mut b1 = BytesMut::from("PUT /one HT");
1553 let mut b2 = BytesMut::from("DELETE /two HT");
1554 assert!(r1.decode(&mut b1).unwrap().is_none());
1555 assert!(r2.decode(&mut b2).unwrap().is_none());
1556 b1.extend_from_slice(b"TP/1.1\r\nhost: a\r\n\r\n");
1557 b2.extend_from_slice(b"TP/1.0\r\n\r\n");
1558 let req = r1.decode(&mut b1).unwrap().unwrap().0;
1559 assert_eq!((req.method(), req.path()), (&Method::PUT, "/one"));
1560 let req = r2.decode(&mut b2).unwrap().unwrap().0;
1561 assert_eq!((req.method(), req.path()), (&Method::DELETE, "/two"));
1562 }
1563
1564 #[test]
1565 fn test_leading_empty_lines() {
1566 let reader = MessageDecoder::<Request>::default();
1567 let mut buf = BytesMut::new();
1568 for _ in 0..10 {
1569 buf.extend_from_slice(b"\r\n");
1570 assert!(reader.decode(&mut buf).unwrap().is_none());
1571 assert!(buf.is_empty());
1572 }
1573 buf.extend_from_slice(b"\nGET /test HTTP/1.1\r\nhost: a\r\n\r\n");
1574 let req = reader.decode(&mut buf).unwrap().unwrap().0;
1575 assert_eq!(req.path(), "/test");
1576
1577 let cfg: SharedCfg = SharedCfg::new("test")
1579 .add(HttpServiceConfig::new().set_max_buf_size(10))
1580 .into();
1581 let reader = MessageDecoder::<Request>::new(cfg.get());
1582 let mut buf = BytesMut::new();
1583 let mut res = Ok(None);
1584 for _ in 0..6 {
1585 buf.extend_from_slice(b"\r\n");
1586 res = reader.decode(&mut buf);
1587 if res.is_err() {
1588 break;
1589 }
1590 }
1591 assert_eq!(res.err(), Some(DecodeError::TooLarge(12)));
1592 }
1593
1594 #[test]
1595 fn test_max_start_line_size() {
1596 let cfg: SharedCfg = SharedCfg::new("test")
1597 .add(HttpServiceConfig::new().set_max_start_line_size(32))
1598 .into();
1599
1600 let line = format!("GET /{} HTTP/1.1\r\n", "a".repeat(16));
1602 assert_eq!(line.len(), 32);
1603 let reader = MessageDecoder::<Request>::new(cfg.get());
1604 let mut buf = BytesMut::from(format!("{line}host: a\r\n\r\n").as_str());
1605 assert!(reader.decode(&mut buf).unwrap().is_some());
1606
1607 let reader = MessageDecoder::<Request>::new(cfg.get());
1608 let mut buf = BytesMut::from(format!("GET /{} HTTP/1.1\r\n\r\n", "a".repeat(17)).as_str());
1609 assert_eq!(
1610 reader.decode(&mut buf).err(),
1611 Some(DecodeError::StartLineTooLong(33))
1612 );
1613
1614 let reader = MessageDecoder::<Request>::new(cfg.get());
1616 let mut buf = BytesMut::from("GET /");
1617 assert!(reader.decode(&mut buf).unwrap().is_none());
1618 buf.extend_from_slice("a".repeat(27).as_bytes());
1619 assert!(reader.decode(&mut buf).unwrap().is_none());
1620 buf.extend_from_slice(b"a");
1621 assert_eq!(
1622 reader.decode(&mut buf).err(),
1623 Some(DecodeError::StartLineTooLong(33))
1624 );
1625
1626 let reader = MessageDecoder::<Request>::new(cfg.get());
1628 let mut buf = BytesMut::from(
1629 format!("GET / HTTP/1.1\r\nhost: a\r\nx: {}\r\n\r\n", "a".repeat(64)).as_str(),
1630 );
1631 assert!(reader.decode(&mut buf).unwrap().is_some());
1632
1633 let reader = MessageDecoder::<Request>::default();
1635 let mut buf = BytesMut::from(format!("GET /{}", "a".repeat(16 * 1024)).as_str());
1636 assert!(matches!(
1637 reader.decode(&mut buf),
1638 Err(DecodeError::StartLineTooLong(_))
1639 ));
1640 }
1641
1642 #[test]
1643 fn test_parse() {
1644 let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nhost: localhost\r\n\r\n");
1645
1646 let reader = MessageDecoder::<Request>::default();
1647 match reader.decode(&mut buf) {
1648 Ok(Some((req, _))) => {
1649 assert_eq!(req.version(), Version::HTTP_11);
1650 assert_eq!(*req.method(), Method::GET);
1651 assert_eq!(req.path(), "/test");
1652 }
1653 Ok(_) | Err(_) => unreachable!("Error during parsing http request"),
1654 }
1655
1656 let mut buf =
1657 BytesMut::from("GET /test HTTP/1.1\r\nhost: localhost\r\ncontent-length:512\r\n\r\n");
1658 let reader = MessageDecoder::<Request>::default();
1659 let req = reader.decode(&mut buf).unwrap().unwrap().0;
1660 assert_eq!(req.version(), Version::HTTP_11);
1661 assert_eq!(*req.method(), Method::GET);
1662 assert_eq!(req.path(), "/test");
1663 }
1664
1665 #[test]
1666 fn test_connection_flags() {
1667 for s in ["Close", "close,", "close ", " close", "\tclose"] {
1668 assert_eq!(connection_flags(s.as_bytes()), Flags::CONN_CLOSE);
1669 }
1670 for s in ["upgrade", "upGrade", "upgrade,", "upgrade "] {
1671 assert_eq!(connection_flags(s.as_bytes()), Flags::CONN_UPGRADE);
1672 }
1673 for s in ["keep-alive", "keep-Alive", "keep-alive,", "Keep-alive "] {
1674 assert_eq!(connection_flags(s.as_bytes()), Flags::CONN_KA);
1675 }
1676 for s in [
1677 "keep-aliv",
1678 "clos",
1679 "upgrad",
1680 "closed",
1681 "close-x",
1682 "upgrades",
1683 "x-close",
1684 "keep-alivex",
1685 "",
1686 ] {
1687 assert_eq!(connection_flags(s.as_bytes()), Flags::empty(), "{s:?}");
1688 }
1689 assert_eq!(connection_flags(b"te, trailers, close"), Flags::CONN_CLOSE);
1691 assert_eq!(
1692 connection_flags(b"keep-alive, Upgrade"),
1693 Flags::CONN_KA | Flags::CONN_UPGRADE
1694 );
1695 }
1696
1697 #[test]
1698 fn test_conn_multiple_tokens() {
1699 let mut buf = BytesMut::from(
1700 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
1701 connection: te, trailers, close\r\n\r\n",
1702 );
1703 let req = parse_ready!(&mut buf);
1704 assert_eq!(req.head().connection_type(), ConnectionType::Close);
1705
1706 let mut buf = BytesMut::from(
1707 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
1708 connection: closed\r\n\r\n",
1709 );
1710 let req = parse_ready!(&mut buf);
1711 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
1712
1713 let mut buf = BytesMut::from(
1715 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
1716 connection: close\r\n\
1717 connection: keep-alive\r\n\r\n",
1718 );
1719 let req = parse_ready!(&mut buf);
1720 assert_eq!(req.head().connection_type(), ConnectionType::Close);
1721
1722 let mut buf = BytesMut::from(
1723 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
1724 upgrade: websocket\r\n\
1725 connection: keep-alive, Upgrade\r\n\r\n",
1726 );
1727 let req = parse_ready!(&mut buf);
1728 assert!(req.upgrade());
1729 }
1730
1731 #[test]
1732 fn test_parse_partial() {
1733 let mut buf = BytesMut::from("PUT /test HTTP/1");
1734
1735 let reader = MessageDecoder::<Request>::default();
1736 assert!(reader.decode(&mut buf).unwrap().is_none());
1737
1738 buf.extend(b".1\r\nhost: localhost\r\n\r\n");
1739 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1740 assert_eq!(req.version(), Version::HTTP_11);
1741 assert_eq!(*req.method(), Method::PUT);
1742 assert_eq!(req.path(), "/test");
1743 }
1744
1745 #[test]
1746 fn parse_header_name_origins() {
1747 let mut buf = BytesMut::from(
1749 "GET /test2 HTTP/1.0\r\n\
1750 Test: 123\r\n\
1751 Content-Length: 0\r\n\
1752 \r\n",
1753 );
1754
1755 let reader = MessageDecoder::<Request>::new(Cfg::default());
1756 let (req, _) = reader.decode(&mut buf.clone()).unwrap().unwrap();
1757 assert_eq!(req.head().headers_vec().len(), 0);
1758
1759 let cfg: SharedCfg = SharedCfg::new("dbg")
1760 .add(HttpServiceConfig::default().set_headers_vec(true))
1761 .into();
1762 let reader = MessageDecoder::<Request>::new(cfg.get());
1763 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1764 assert_eq!(
1765 req.head().headers_vec()[0].name,
1766 HeaderName::try_from("test").unwrap()
1767 );
1768 assert_eq!(req.head().headers_vec()[0].origin, "Test");
1769 assert_eq!(req.head().headers_vec()[1].name, header::CONTENT_LENGTH);
1770 assert_eq!(req.head().headers_vec()[1].origin, "Content-Length");
1771
1772 let mut buf = BytesMut::from(
1774 "HTTP/1.0 200 Ok\r\n\
1775 TEST: 123\r\n\
1776 Content-Length: 0\r\n\
1777 tesT: 456\r\n\
1778 \r\n",
1779 );
1780
1781 let reader = MessageDecoder::<ResponseHead>::new(Cfg::default());
1782 let (res, _) = reader.decode(&mut buf.clone()).unwrap().unwrap();
1783 assert_eq!(res.headers_vec().len(), 0);
1784
1785 let cfg: SharedCfg = SharedCfg::new("dbg")
1786 .add(HttpServiceConfig::default().set_headers_vec(true))
1787 .into();
1788 let reader = MessageDecoder::<ResponseHead>::new(cfg.get());
1789 let (res, _) = reader.decode(&mut buf).unwrap().unwrap();
1790 assert_eq!(
1791 res.headers_vec()[0].name,
1792 HeaderName::try_from("test").unwrap()
1793 );
1794 assert_eq!(res.headers_vec()[0].origin, "TEST");
1795 assert_eq!(res.headers_vec()[0].value, "123");
1796 assert_eq!(res.headers_vec()[1].name, header::CONTENT_LENGTH);
1797 assert_eq!(res.headers_vec()[1].origin, "Content-Length");
1798 assert_eq!(res.headers_vec()[2].origin, "tesT");
1799 assert_eq!(res.headers_vec()[2].value, "456");
1800 }
1801
1802 #[test]
1803 fn parse_header_values_split_from_buffer() {
1804 const LONG_NAME: &str = "X-A-Very-Long-Header-Name-Over-Inline";
1805 const LONG_VALUE: &str = "a value longer than the inline capacity of bytes";
1806 let text = format!(
1807 "POST /test HTTP/1.1\r\n\
1808 Host: a\r\n\
1809 X-Empty:\r\n\
1810 X-Ws: \t \r\n\
1811 {LONG_NAME}: \t{LONG_VALUE} \t\r\n\
1812 Short: v\r\n\
1813 Content-Length: 4\r\n\
1814 \r\n\
1815 body"
1816 );
1817
1818 for headers_vec in [false, true] {
1819 let cfg: SharedCfg = SharedCfg::new("dbg")
1820 .add(HttpServiceConfig::default().set_headers_vec(headers_vec))
1821 .into();
1822 for chunk in [text.len(), 1] {
1823 let reader = MessageDecoder::<Request>::new(cfg.get());
1824 let mut buf = BytesMut::new();
1825 let mut req = None;
1826 let mut fed = 0;
1827 for part in text.as_bytes().chunks(chunk) {
1828 buf.extend_from_slice(part);
1829 fed += part.len();
1830 if let Some((r, _)) = reader.decode(&mut buf).unwrap() {
1831 req = Some(r);
1832 break;
1833 }
1834 }
1835 buf.extend_from_slice(&text.as_bytes()[fed..]);
1836 let req = req.unwrap();
1837 let ctx = format!("headers_vec {headers_vec} chunk {chunk}");
1838 assert_eq!(&buf[..], b"body", "{ctx}");
1839
1840 let h = req.headers();
1841 assert_eq!(h.get("x-empty").unwrap(), "", "{ctx}");
1842 assert_eq!(h.get("x-ws").unwrap(), "", "{ctx}");
1843 assert_eq!(h.get(LONG_NAME).unwrap(), LONG_VALUE, "{ctx}");
1844 assert_eq!(h.get("short").unwrap(), "v", "{ctx}");
1845 assert_eq!(h.get(header::CONTENT_LENGTH).unwrap(), "4", "{ctx}");
1846
1847 let items = req.head().headers_vec();
1848 if headers_vec {
1849 let origins: Vec<_> = items.iter().map(|i| &i.origin[..]).collect();
1850 assert_eq!(
1851 origins,
1852 [
1853 "Host",
1854 "X-Empty",
1855 "X-Ws",
1856 LONG_NAME,
1857 "Short",
1858 "Content-Length"
1859 ],
1860 "{ctx}"
1861 );
1862 let values: Vec<_> = items.iter().map(|i| i.value.as_bytes()).collect();
1863 let expected: [&[u8]; 6] = [b"a", b"", b"", LONG_VALUE.as_bytes(), b"v", b"4"];
1864 assert_eq!(values, expected, "{ctx}");
1865 } else {
1866 assert!(items.is_empty(), "{ctx}");
1867 }
1868 }
1869 }
1870 }
1871
1872 #[test]
1873 fn parse_h10_get() {
1874 let mut buf = BytesMut::from(
1875 "GET /test1 HTTP/1.0\r\n\
1876 \r\n\
1877 abc",
1878 );
1879
1880 let reader = MessageDecoder::<Request>::default();
1881 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1882 assert_eq!(req.version(), Version::HTTP_10);
1883 assert_eq!(*req.method(), Method::GET);
1884 assert_eq!(req.path(), "/test1");
1885
1886 let mut buf = BytesMut::from(
1887 "GET /test2 HTTP/1.0\r\n\
1888 Test: 123\r\n\
1889 Content-Length: 0\r\n\
1890 \r\n",
1891 );
1892
1893 let reader = MessageDecoder::<Request>::default();
1894 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1895 assert_eq!(req.version(), Version::HTTP_10);
1896 assert_eq!(*req.method(), Method::GET);
1897 assert_eq!(req.path(), "/test2");
1898
1899 let mut buf = BytesMut::from(
1900 "GET /test3?test=1 HTTP/1.0\r\n\
1901 Content-Length: 3\r\n\
1902 \r\n
1903 abc",
1904 );
1905
1906 let reader = MessageDecoder::<Request>::default();
1907 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1908 assert_eq!(req.version(), Version::HTTP_10);
1909 assert_eq!(*req.method(), Method::GET);
1910 assert_eq!(req.path(), "/test3");
1911 assert_eq!(req.uri().query().unwrap(), "test=1");
1912
1913 let mut buf =
1915 BytesMut::from("GET /test3?test=1 HTTP/1.0\r\nTransfer-Encoding: chunked\r\n\r\n");
1916 expect_parse_err!(&mut buf);
1917 }
1918
1919 #[test]
1920 fn parse_h10_post() {
1921 let mut buf = BytesMut::from(
1922 "POST /test1 HTTP/1.0\r\n\
1923 Content-Length: 3\r\n\
1924 \r\n\
1925 abc",
1926 );
1927
1928 let reader = MessageDecoder::<Request>::default();
1929 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1930 assert_eq!(req.version(), Version::HTTP_10);
1931 assert_eq!(*req.method(), Method::POST);
1932 assert_eq!(req.path(), "/test1");
1933
1934 let mut buf = BytesMut::from(
1935 "POST /test2 HTTP/1.0\r\n\
1936 Content-Length: 0\r\n\
1937 \r\n",
1938 );
1939
1940 let reader = MessageDecoder::<Request>::default();
1941 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1942 assert_eq!(req.version(), Version::HTTP_10);
1943 assert_eq!(*req.method(), Method::POST);
1944 assert_eq!(req.path(), "/test2");
1945
1946 let mut buf = BytesMut::from(
1947 "POST /test3 HTTP/1.0\r\n\
1948 \r\n",
1949 );
1950 let reader = MessageDecoder::<Request>::default();
1951 let err = reader.decode(&mut buf).unwrap_err();
1952 assert!(err.to_string().contains("Header"));
1953 }
1954
1955 #[test]
1956 fn test_parse_body() {
1957 let mut buf = BytesMut::from(
1958 "GET /test HTTP/1.1\r\nhost: localhost\r\nContent-Length: 4\r\n\r\nbody",
1959 );
1960
1961 let reader = MessageDecoder::<Request>::default();
1962 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1963 let pl = pl.unwrap();
1964 assert_eq!(req.version(), Version::HTTP_11);
1965 assert_eq!(*req.method(), Method::GET);
1966 assert_eq!(req.path(), "/test");
1967 assert_eq!(
1968 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
1969 b"body"
1970 );
1971 }
1972
1973 #[test]
1974 fn test_parse_body_crlf() {
1975 let mut buf = BytesMut::from(
1976 "\r\nGET /test HTTP/1.1\r\nhost: localhost\r\nContent-Length: 4\r\n\r\nbody",
1977 );
1978
1979 let reader = MessageDecoder::<Request>::default();
1980 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1981 let pl = pl.unwrap();
1982 assert_eq!(req.version(), Version::HTTP_11);
1983 assert_eq!(*req.method(), Method::GET);
1984 assert_eq!(req.path(), "/test");
1985 assert_eq!(
1986 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
1987 b"body"
1988 );
1989 }
1990
1991 #[test]
1992 fn test_parse_partial_eof() {
1993 let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nhost: localhost\r\n");
1994 let reader = MessageDecoder::<Request>::default();
1995 assert!(reader.decode(&mut buf).unwrap().is_none());
1996
1997 buf.extend(b"\r\n");
1998 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
1999 assert_eq!(req.version(), Version::HTTP_11);
2000 assert_eq!(*req.method(), Method::GET);
2001 assert_eq!(req.path(), "/test");
2002 }
2003
2004 #[test]
2005 fn test_headers_split_field() {
2006 let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nhost: localhost\r\n");
2007
2008 let reader = MessageDecoder::<Request>::default();
2009 assert! { reader.decode(&mut buf).unwrap().is_none() }
2010
2011 buf.extend(b"t");
2012 assert! { reader.decode(&mut buf).unwrap().is_none() }
2013
2014 buf.extend(b"es");
2015 assert! { reader.decode(&mut buf).unwrap().is_none() }
2016
2017 buf.extend(b"t: value\r\n\r\n");
2018 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2019 assert_eq!(req.version(), Version::HTTP_11);
2020 assert_eq!(*req.method(), Method::GET);
2021 assert_eq!(req.path(), "/test");
2022 assert_eq!(
2023 req.headers()
2024 .get(HeaderName::try_from("test").unwrap())
2025 .unwrap()
2026 .as_bytes(),
2027 b"value"
2028 );
2029 }
2030
2031 #[test]
2032 fn test_headers_multi_value() {
2033 let mut buf = BytesMut::from(
2034 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2035 Set-Cookie: c1=cookie1\r\n\
2036 Set-Cookie: c2=cookie2\r\n\r\n",
2037 );
2038 let reader = MessageDecoder::<Request>::default();
2039 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2040
2041 let val: Vec<_> = req
2042 .headers()
2043 .get_all(SET_COOKIE)
2044 .map(|v| v.to_str().unwrap().to_owned())
2045 .collect();
2046 assert_eq!(val[0], "c1=cookie1");
2047 assert_eq!(val[1], "c2=cookie2");
2048 }
2049
2050 #[test]
2051 fn test_conn_default_1_0() {
2052 let mut buf = BytesMut::from("GET /test HTTP/1.0\r\n\r\n");
2053 let req = parse_ready!(&mut buf);
2054
2055 assert_eq!(req.head().connection_type(), ConnectionType::Close);
2056 }
2057
2058 #[test]
2059 fn test_conn_default_1_1() {
2060 let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nhost: localhost\r\n\r\n");
2061 let req = parse_ready!(&mut buf);
2062
2063 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2064 }
2065
2066 #[test]
2067 fn test_conn_close() {
2068 let mut buf = BytesMut::from(
2069 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2070 connection: close\r\n\r\n",
2071 );
2072 let req = parse_ready!(&mut buf);
2073
2074 assert_eq!(req.head().connection_type(), ConnectionType::Close);
2075
2076 let mut buf = BytesMut::from(
2077 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2078 connection: Close\r\n\r\n",
2079 );
2080 let req = parse_ready!(&mut buf);
2081
2082 assert_eq!(req.head().connection_type(), ConnectionType::Close);
2083 }
2084
2085 #[test]
2086 fn test_conn_close_1_0() {
2087 let mut buf = BytesMut::from(
2088 "GET /test HTTP/1.0\r\n\
2089 connection: close\r\n\r\n",
2090 );
2091
2092 let req = parse_ready!(&mut buf);
2093
2094 assert_eq!(req.head().connection_type(), ConnectionType::Close);
2095 }
2096
2097 #[test]
2098 fn test_conn_keep_alive_1_0() {
2099 let mut buf = BytesMut::from(
2100 "GET /test HTTP/1.0\r\n\
2101 connection: keep-alive\r\n\r\n",
2102 );
2103 let req = parse_ready!(&mut buf);
2104
2105 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2106
2107 let mut buf = BytesMut::from(
2108 "GET /test HTTP/1.0\r\n\
2109 connection: Keep-Alive\r\n\r\n",
2110 );
2111 let req = parse_ready!(&mut buf);
2112
2113 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2114 }
2115
2116 #[test]
2117 fn test_conn_keep_alive_1_1() {
2118 let mut buf = BytesMut::from(
2119 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2120 connection: keep-alive\r\n\r\n",
2121 );
2122 let req = parse_ready!(&mut buf);
2123
2124 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2125 }
2126
2127 #[test]
2128 fn test_conn_other_1_0() {
2129 let mut buf = BytesMut::from(
2130 "GET /test HTTP/1.0\r\n\
2131 connection: other\r\n\r\n",
2132 );
2133 let req = parse_ready!(&mut buf);
2134
2135 assert_eq!(req.head().connection_type(), ConnectionType::Close);
2136 }
2137
2138 #[test]
2139 fn test_conn_other_1_1() {
2140 let mut buf = BytesMut::from(
2141 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2142 connection: other\r\n\r\n",
2143 );
2144 let req = parse_ready!(&mut buf);
2145
2146 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2147 }
2148
2149 #[test]
2150 fn test_conn_upgrade() {
2151 let mut buf = BytesMut::from(
2152 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2153 upgrade: websockets\r\n\
2154 connection: upgrade\r\n\r\n",
2155 );
2156 let req = parse_ready!(&mut buf);
2157
2158 assert!(req.upgrade());
2159 assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
2160
2161 let mut buf = BytesMut::from(
2162 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2163 upgrade: Websockets\r\n\
2164 connection: Upgrade\r\n\r\n",
2165 );
2166 let req = parse_ready!(&mut buf);
2167
2168 assert!(req.upgrade());
2169 assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
2170 }
2171
2172 #[test]
2173 fn test_upgrade_requires_connection_option() {
2174 let reader = MessageDecoder::<Request>::default();
2175 for req in [
2176 "GET /test HTTP/1.1\r\nhost: a\r\nupgrade: websocket\r\n\r\n",
2177 "GET /test HTTP/1.1\r\nhost: a\r\nconnection: upgrade\r\n\r\n",
2178 "GET /test HTTP/1.1\r\nhost: a\r\nconnection: keep-alive\r\n\
2179 upgrade: websocket\r\ncontent-length: 0\r\n\r\n",
2180 ] {
2181 let mut buf =
2182 BytesMut::from(format!("{req}GET /next HTTP/1.1\r\nhost: a\r\n\r\n").as_str());
2183 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2184 assert!(!req.upgrade(), "{req:?}");
2185 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2186 assert_eq!(pl, PayloadType::None);
2187 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2189 assert_eq!(req.path(), "/next");
2190 }
2191
2192 let mut buf = BytesMut::from(
2194 "POST /test HTTP/1.1\r\nhost: a\r\nupgrade: h2c\r\n\
2195 content-length: 4\r\n\r\nbody",
2196 );
2197 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2198 assert!(!req.upgrade());
2199 assert!(matches!(pl, PayloadType::Payload(_)));
2200 assert_eq!(req.headers().get(header::UPGRADE).unwrap(), "h2c");
2201
2202 let mut buf = BytesMut::from(
2204 "GET /test HTTP/1.1\r\nhost: a\r\nconnection: keep-alive, Upgrade\r\n\
2205 upgrade: websocket\r\n\r\n",
2206 );
2207 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2208 assert!(req.upgrade());
2209 assert!(matches!(pl, PayloadType::Stream(_)));
2210 }
2211
2212 #[test]
2213 fn test_expect_100_continue() {
2214 let reader = MessageDecoder::<Request>::default();
2215 for (val, expect) in [
2216 ("100-continue", true),
2217 ("100-Continue", true),
2218 (" 100-CONTINUE ", true),
2219 ("foo, 100-continue", true),
2220 ("100-foo", false),
2221 ("100-continuex", false),
2222 ("100", false),
2223 ("", false),
2224 ] {
2225 let mut buf = BytesMut::from(
2226 format!(
2227 "POST /test HTTP/1.1\r\nhost: a\r\nexpect: {val}\r\ncontent-length: 1\r\n\r\n"
2228 )
2229 .as_str(),
2230 );
2231 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2232 assert_eq!(req.head().expect(), expect, "{val:?}");
2233 }
2234 }
2235
2236 #[test]
2237 fn test_http10_ignores_expect_and_upgrade() {
2238 let mut buf = BytesMut::from(
2239 "GET /test HTTP/1.0\r\n\
2240 connection: keep-alive, upgrade\r\n\
2241 upgrade: websocket\r\n\
2242 expect: 100-continue\r\n\r\n\
2243 GET /next HTTP/1.0\r\n\r\n",
2244 );
2245 let reader = MessageDecoder::<Request>::default();
2246 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2247 assert!(!req.upgrade());
2248 assert!(!req.head().expect());
2249 assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
2250 assert_eq!(pl, PayloadType::None);
2251 assert_eq!(req.headers().get(header::UPGRADE).unwrap(), "websocket");
2253 assert_eq!(req.headers().get(header::EXPECT).unwrap(), "100-continue");
2254 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2256 assert_eq!(req.path(), "/next");
2257
2258 let mut buf = BytesMut::from(
2260 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2261 connection: upgrade\r\n\
2262 upgrade: websocket\r\n\
2263 expect: 100-continue\r\n\r\n",
2264 );
2265 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2266 assert!(req.upgrade());
2267 assert!(req.head().expect());
2268 assert!(matches!(pl, PayloadType::Stream(_)));
2269 }
2270
2271 #[test]
2272 fn test_host_validation() {
2273 let reader = MessageDecoder::<Request>::default();
2274 for req in [
2275 "GET / HTTP/1.1\r\n\r\n",
2276 "GET / HTTP/1.1\r\nhost: a\r\nhost: a\r\n\r\n",
2277 "GET / HTTP/1.0\r\nhost: a\r\nhost: b\r\n\r\n",
2278 "GET / HTTP/1.1\r\nhost: [email protected]\r\n\r\n",
2279 "GET / HTTP/1.1\r\nhost: exa mple.com\r\n\r\n",
2280 "GET / HTTP/1.1\r\nhost: example.com/path\r\n\r\n",
2281 "GET / HTTP/1.1\r\nhost: example.com:port\r\n\r\n",
2282 "GET / HTTP/1.1\r\nhost: [::1]:x\r\n\r\n",
2283 "GET / HTTP/1.1\r\nhost: a:1:2\r\n\r\n",
2284 "GET / HTTP/1.1\r\nhost: @\r\n\r\n",
2285 "GET / HTTP/1.1\r\nhost: example.com:99999\r\n\r\n",
2286 "GET / HTTP/1.1\r\nhost: 256.0.0.1\r\n\r\n",
2287 "GET / HTTP/1.1\r\nhost: [::1\r\n\r\n",
2288 "GET / HTTP/1.1\r\nhost: [::1]]\r\n\r\n",
2289 "GET / HTTP/1.1\r\nhost: [1:2:3:4:5:6:7:8:9]\r\n\r\n",
2290 "GET / HTTP/1.1\r\nhost: a%\r\n\r\n",
2291 "GET / HTTP/1.1\r\nhost: a{b}\r\n\r\n",
2292 "GET / HTTP/1.1\r\nhost: \u{e9}\r\n\r\n",
2293 ] {
2294 let mut buf = BytesMut::from(req);
2295 assert_eq!(
2296 reader.decode(&mut buf).err(),
2297 Some(DecodeError::Header),
2298 "{req:?}"
2299 );
2300 }
2301
2302 for req in [
2303 "GET / HTTP/1.0\r\n\r\n",
2304 "GET / HTTP/1.1\r\nhost:\r\n\r\n",
2305 "GET / HTTP/1.1\r\nhost: example.com\r\n\r\n",
2306 "GET / HTTP/1.1\r\nHost: example.com:8080\r\n\r\n",
2307 "GET / HTTP/1.1\r\nhost: 127.0.0.1:80\r\n\r\n",
2308 "GET / HTTP/1.1\r\nhost: [::1]:80\r\n\r\n",
2309 "GET / HTTP/1.1\r\nhost: [::1]\r\n\r\n",
2310 "GET / HTTP/1.1\r\nhost: example.com:\r\n\r\n",
2311 "GET / HTTP/1.1\r\nhost: a-b_c~d!$&'()*+,;=\r\n\r\n",
2312 "GET http://example.com/ HTTP/1.1\r\nhost: example.com\r\n\r\n",
2313 ] {
2314 let mut buf = BytesMut::from(req);
2315 assert!(reader.decode(&mut buf).unwrap().is_some(), "{req:?}");
2316 }
2317
2318 let cfg: SharedCfg = SharedCfg::new("test")
2320 .add(HttpServiceConfig::new().set_host_validation(false))
2321 .into();
2322 let reader = MessageDecoder::<Request>::new(cfg.get());
2323 let mut buf = BytesMut::from(
2324 "GET / HTTP/1.1\r\n\r\n\
2325 GET / HTTP/1.1\r\nhost: a\r\nhost: user@b\r\n\r\n",
2326 );
2327 assert!(reader.decode(&mut buf).unwrap().is_some());
2328 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2329 assert_eq!(req.headers().get_all(header::HOST).count(), 2);
2330
2331 let reader = MessageDecoder::<ResponseHead>::default();
2333 let mut buf = BytesMut::from("HTTP/1.1 200 OK\r\nhost: a\r\nhost: b\r\n\r\n");
2334 assert!(reader.decode(&mut buf).unwrap().is_some());
2335 }
2336
2337 #[test]
2338 fn test_conn_upgrade_connect_method() {
2339 let mut buf = BytesMut::from(
2340 "CONNECT localhost:443 HTTP/1.1\r\nhost: localhost\r\n\
2341 content-type: text/plain\r\n\r\n",
2342 );
2343 let req = parse_ready!(&mut buf);
2344
2345 assert!(req.upgrade());
2346 }
2347
2348 #[test]
2349 fn test_request_chunked() {
2350 let mut buf = BytesMut::from(
2351 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2352 transfer-encoding: chunked\r\n\r\n",
2353 );
2354 let req = parse_ready!(&mut buf);
2355
2356 if let Ok(val) = req.chunked() {
2357 assert!(val);
2358 } else {
2359 unreachable!("Error");
2360 }
2361
2362 let mut buf = BytesMut::from(
2364 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2365 transfer-encoding: chnked\r\n\r\n",
2366 );
2367 expect_parse_err!(&mut buf);
2368 }
2369
2370 #[test]
2371 fn test_headers_content_length_err_1() {
2372 let mut buf = BytesMut::from(
2373 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2374 content-length: line\r\n\r\n",
2375 );
2376
2377 expect_parse_err!(&mut buf);
2378 }
2379
2380 #[test]
2381 fn test_headers_content_length_err_2() {
2382 let mut buf = BytesMut::from(
2383 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2384 content-length: -1\r\n\r\n",
2385 );
2386
2387 expect_parse_err!(&mut buf);
2388 }
2389
2390 #[test]
2391 fn test_invalid_header() {
2392 let mut buf = BytesMut::from(
2393 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2394 test line\r\n\r\n",
2395 );
2396
2397 expect_parse_err!(&mut buf);
2398 }
2399
2400 #[test]
2401 fn test_invalid_name() {
2402 let mut buf = BytesMut::from(
2403 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2404 test[]: line\r\n\r\n",
2405 );
2406
2407 expect_parse_err!(&mut buf);
2408 }
2409
2410 #[test]
2411 fn test_http_request_bad_status_line() {
2412 let mut buf = BytesMut::from("getpath \r\n\r\n");
2413 expect_parse_err!(&mut buf);
2414 }
2415
2416 #[test]
2417 fn test_http_request_upgrade() {
2418 let mut buf = BytesMut::from(
2419 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2420 connection: upgrade\r\n\
2421 upgrade: websocket\r\n\r\n\
2422 some raw data",
2423 );
2424 let reader = MessageDecoder::<Request>::default();
2425 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2426 assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
2427 assert!(req.upgrade());
2428 assert!(pl.is_unhandled());
2429 }
2430
2431 #[test]
2432 fn test_http_request_upgrade_content_length() {
2433 let reader = MessageDecoder::<Request>::default();
2434
2435 for hdrs in [
2437 "content-length: 0\r\nupgrade: websocket\r\n",
2438 "upgrade: websocket\r\ncontent-length: 0\r\n",
2439 ] {
2440 let mut buf = BytesMut::from(
2441 format!(
2442 "GET /test HTTP/1.1\r\nhost: localhost\r\nconnection: upgrade\r\n{hdrs}\r\nraw"
2443 )
2444 .as_str(),
2445 );
2446 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2447 assert!(req.upgrade(), "{hdrs:?}");
2448 assert!(pl.is_unhandled(), "{hdrs:?}");
2449 }
2450
2451 for hdrs in [
2453 "content-length: 4\r\nupgrade: websocket\r\n",
2454 "upgrade: websocket\r\ncontent-length: 4\r\n",
2455 ] {
2456 let mut buf = BytesMut::from(
2457 format!(
2458 "GET /test HTTP/1.1\r\nhost: localhost\r\nconnection: upgrade\r\n{hdrs}\r\ndata"
2459 )
2460 .as_str(),
2461 );
2462 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
2463 let pl = pl.unwrap();
2464 assert_eq!(
2465 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
2466 b"data"
2467 );
2468 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2469 }
2470
2471 let mut buf = BytesMut::from(
2473 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2474 content-length: 4\r\n\
2475 upgrade: websocket\r\n\
2476 content-length: 10\r\n\r\n",
2477 );
2478 assert!(reader.decode(&mut buf).is_err());
2479 }
2480
2481 #[test]
2482 fn test_http_request_parser_utf8() {
2483 let mut buf = BytesMut::from(
2484 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2485 x-test: тест\r\n\r\n",
2486 );
2487 let req = parse_ready!(&mut buf);
2488
2489 assert_eq!(
2490 req.headers().get("x-test").unwrap().as_bytes(),
2491 "тест".as_bytes()
2492 );
2493 }
2494
2495 #[test]
2496 fn test_http_request_parser_two_slashes() {
2497 let mut buf = BytesMut::from("GET //path HTTP/1.1\r\nhost: localhost\r\n\r\n");
2498 let req = parse_ready!(&mut buf);
2499
2500 assert_eq!(req.path(), "//path");
2501 assert!(req.uri().authority().is_none());
2502 }
2503
2504 #[test]
2505 fn test_http_request_parser_bad_method() {
2506 let mut buf = BytesMut::from("!12%()+=~$ /get HTTP/1.1\r\nhost: localhost\r\n\r\n");
2507
2508 expect_parse_err!(&mut buf);
2509 }
2510
2511 #[test]
2512 fn test_http_request_parser_bad_version() {
2513 let mut buf = BytesMut::from("GET //get HT/11\r\n\r\n");
2514
2515 expect_parse_err!(&mut buf);
2516 }
2517
2518 #[test]
2519 fn test_http_request_chunked_payload() {
2520 let mut buf = BytesMut::from(
2521 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2522 transfer-encoding: chunked\r\n\r\n",
2523 );
2524 let reader = MessageDecoder::<Request>::default();
2525 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2526 let pl = pl.unwrap();
2527 assert!(req.chunked().unwrap());
2528
2529 buf.extend(b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n");
2530 assert_eq!(
2531 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
2532 b"dataline"
2533 );
2534 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2535 }
2536
2537 #[test]
2538 fn test_http_request_chunked_payload_and_next_message() {
2539 let mut buf = BytesMut::from(
2540 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2541 transfer-encoding: chunked\r\n\r\n",
2542 );
2543 let reader = MessageDecoder::<Request>::default();
2544 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2545 let pl = pl.unwrap();
2546 assert!(req.chunked().unwrap());
2547
2548 buf.extend(
2549 b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n\
2550 POST /test2 HTTP/1.1\r\nhost: localhost\r\n\
2551 transfer-encoding: chunked\r\n\r\n"
2552 .iter(),
2553 );
2554 let msg = pl.decode(&mut buf).unwrap().unwrap();
2555 assert_eq!(msg.chunk().as_ref(), b"dataline");
2556 let msg = pl.decode(&mut buf).unwrap().unwrap();
2557 assert!(msg.eof());
2558
2559 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2560 assert!(req.chunked().unwrap());
2561 assert_eq!(*req.method(), Method::POST);
2562 assert!(req.chunked().unwrap());
2563 }
2564
2565 #[test]
2566 fn test_http_request_chunked_payload_chunks() {
2567 let mut buf = BytesMut::from(
2568 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2569 transfer-encoding: chunked\r\n\r\n",
2570 );
2571
2572 let reader = MessageDecoder::<Request>::default();
2573 let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
2574 let pl = pl.unwrap();
2575 assert!(req.chunked().unwrap());
2576
2577 buf.extend(b"4\r\n1111\r\n");
2578 let msg = pl.decode(&mut buf).unwrap().unwrap();
2579 assert_eq!(msg.chunk().as_ref(), b"1111");
2580
2581 buf.extend(b"4\r\ndata\r");
2582 let msg = pl.decode(&mut buf).unwrap().unwrap();
2583 assert_eq!(msg.chunk().as_ref(), b"data");
2584
2585 buf.extend(b"\n4");
2586 assert!(pl.decode(&mut buf).unwrap().is_none());
2587
2588 buf.extend(b"\r");
2589 assert!(pl.decode(&mut buf).unwrap().is_none());
2590 buf.extend(b"\n");
2591 assert!(pl.decode(&mut buf).unwrap().is_none());
2592
2593 buf.extend(b"li");
2594 let msg = pl.decode(&mut buf).unwrap().unwrap();
2595 assert_eq!(msg.chunk().as_ref(), b"li");
2596
2597 buf.extend(b"ne\r\n0\r\n");
2598 let msg = pl.decode(&mut buf).unwrap().unwrap();
2599 assert_eq!(msg.chunk().as_ref(), b"ne");
2600 assert!(pl.decode(&mut buf).unwrap().is_none());
2601
2602 buf.extend(b"\r\n");
2603 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2604 }
2605
2606 #[test]
2607 fn test_chunked_trailers_limit() {
2608 let decode = |trailers: &[u8], split: bool| {
2609 let (pl, mut buf) = chunked_payload();
2610 buf.extend_from_slice(b"4\r\ndata\r\n0\r\n");
2611 assert_eq!(pl.decode(&mut buf).unwrap().unwrap().chunk().len(), 4);
2612
2613 let mut data = trailers.to_vec();
2614 data.extend_from_slice(b"\r\n");
2615 let step = if split { 1 } else { data.len() };
2616 for part in data.chunks(step) {
2617 buf.extend_from_slice(part);
2618 match pl.decode(&mut buf) {
2619 Ok(None) => (),
2620 Ok(Some(item)) => return Ok(matches!(item, PayloadItem::Trailers(_))),
2621 Err(err) => return Err(err),
2622 }
2623 }
2624 Ok(false)
2625 };
2626 let max = MAX_CHUNK_TRAILERS as usize;
2627
2628 let field = |len: usize| format!("x: {}\r\n", "v".repeat(len - 5)).into_bytes();
2630 for split in [false, true] {
2631 assert_eq!(decode(&field(max), split), Ok(true), "{split}");
2632 assert!(
2633 matches!(
2634 decode(&field(max + 1), split),
2635 Err(DecodeError::InvalidInput(_))
2636 ),
2637 "{split}"
2638 );
2639 assert!(
2641 matches!(
2642 decode(&[&b"x: "[..], &vec![b'v'; max * 2]].concat(), split),
2643 Err(DecodeError::InvalidInput(_))
2644 ),
2645 "{split}"
2646 );
2647 }
2648
2649 assert_eq!(decode(&b"x: y\r\n".repeat(max / 6), false), Ok(true));
2651 assert!(matches!(
2652 decode(&b"x: y\r\n".repeat(max / 6 + 1), false),
2653 Err(DecodeError::InvalidInput(_))
2654 ));
2655 }
2656
2657 #[test]
2658 fn test_parse_chunked_payload_trailers() {
2659 let mut buf = BytesMut::from(
2660 "POST /test HTTP/1.1\r\nhost: localhost\r\n\
2661 transfer-encoding: chunked\r\n\r\n\
2662 4\r\ndata\r\n0\r\n\
2663 test: test\r\n\
2664 x-checksum: \tabc 123\r\n\r\n\
2665 GET /next HTTP/1.1\r\nhost: localhost\r\n\r\n",
2666 );
2667 let reader = MessageDecoder::<Request>::default();
2668 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
2669 let pl = pl.unwrap();
2670 assert_eq!(
2671 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
2672 b"data"
2673 );
2674 let Some(PayloadItem::Trailers(trailers)) = pl.decode(&mut buf).unwrap() else {
2675 panic!("trailers are expected")
2676 };
2677 assert_eq!(trailers.len(), 2);
2678 assert_eq!(trailers.get("test").unwrap(), "test");
2679 assert_eq!(trailers.get("x-checksum").unwrap(), "abc 123");
2680 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2681 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2682 assert_eq!(req.path(), "/next");
2683 assert!(buf.is_empty());
2684
2685 let mut buf = BytesMut::from(
2687 "POST /test HTTP/1.1\r\nhost: localhost\r\n\
2688 transfer-encoding: chunked\r\n\r\n",
2689 );
2690 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
2691 let pl = pl.unwrap();
2692 for part in [
2693 "0\r\n",
2694 "te",
2695 "st: te",
2696 "st\r",
2697 "\n",
2698 "a: 1\r\na: ",
2699 "2\r\n",
2700 "\r",
2701 ] {
2702 buf.extend(part.as_bytes());
2703 assert!(pl.decode(&mut buf).unwrap().is_none(), "{part:?}");
2704 }
2705 buf.extend(b"\n");
2706 let Some(PayloadItem::Trailers(trailers)) = pl.decode(&mut buf).unwrap() else {
2707 panic!("trailers are expected")
2708 };
2709 assert_eq!(trailers.get("test").unwrap(), "test");
2710 let values: Vec<_> = trailers.get_all("a").collect();
2711 assert_eq!(values, ["1", "2"]);
2712 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2713 assert!(buf.is_empty());
2714
2715 for trailer in [
2717 "test: te\nst\r\n\r\n",
2718 "test\x00\r\n\r\n",
2719 " test: v\r\n\r\n",
2720 "test: v\rx",
2721 "test\r\n\r\n",
2722 ": v\r\n\r\n",
2723 "te st: v\r\n\r\n",
2724 "test: v\r\n\rx",
2725 "test: v\r\n t\r\n\r\n",
2726 ] {
2727 let mut buf = BytesMut::from(
2728 "POST /test HTTP/1.1\r\nhost: localhost\r\n\
2729 transfer-encoding: chunked\r\n\r\n0\r\n",
2730 );
2731 buf.extend(trailer.as_bytes());
2732 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
2733 assert!(pl.unwrap().decode(&mut buf).is_err(), "{trailer:?}");
2734 }
2735 }
2736
2737 #[test]
2738 fn test_chunked_trailers_after_data() {
2739 let (pl, mut buf) = chunked_payload();
2740 buf.extend_from_slice(b"2\r\nab\r\n0\r\nx: 1\r\n\r\nnext");
2741 assert_eq!(
2742 pl.decode(&mut buf).unwrap(),
2743 Some(PayloadItem::Chunk("ab".into()))
2744 );
2745 let Some(PayloadItem::Trailers(trailers)) = pl.decode(&mut buf).unwrap() else {
2746 panic!("trailers are expected")
2747 };
2748 assert_eq!(trailers.get("x").unwrap(), "1");
2749 assert_eq!(pl.decode(&mut buf).unwrap(), Some(PayloadItem::Eof));
2750 assert_eq!(&buf[..], b"next");
2751 }
2752
2753 #[test]
2754 fn test_parse_chunked_payload_chunk_extension() {
2755 let mut buf = BytesMut::from(
2756 "GET /test HTTP/1.1\r\nhost: localhost\r\n\
2757 transfer-encoding: chunked\r\n\r\n",
2758 );
2759
2760 let reader = MessageDecoder::<Request>::default();
2761 let (msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
2762 let pl = pl.unwrap();
2763 assert!(msg.chunked().unwrap());
2764
2765 buf.extend(b"4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); let chunk = pl.decode(&mut buf).unwrap().unwrap().chunk();
2767 assert_eq!(chunk, Bytes::from_static(b"dataline"));
2768 let msg = pl.decode(&mut buf).unwrap().unwrap();
2769 assert!(msg.eof());
2770 }
2771
2772 fn decode_all(pl: &PayloadDecoder, buf: &mut BytesMut) -> Vec<Bytes> {
2773 let mut items = Vec::new();
2774 while let Some(item) = pl.decode(buf).unwrap() {
2775 match item {
2776 PayloadItem::Chunk(chunk) => items.push(chunk),
2777 PayloadItem::Trailers(_) => (),
2778 PayloadItem::Eof => break,
2779 }
2780 }
2781 items
2782 }
2783
2784 #[test]
2785 fn test_small_chunks_are_merged() {
2786 let (pl, mut buf) = chunked_payload();
2787 for _ in 0..40_000 {
2788 buf.extend_from_slice(b"1\r\na\r\n");
2789 }
2790 buf.extend_from_slice(b"0\r\n\r\n");
2791 let items = decode_all(&pl, &mut buf);
2792 let lens: Vec<_> = items.iter().map(Bytes::len).collect();
2793 assert_eq!(
2794 lens,
2795 [
2796 MAX_MERGED_CHUNKS,
2797 MAX_MERGED_CHUNKS,
2798 40_000 - 2 * MAX_MERGED_CHUNKS
2799 ]
2800 );
2801 assert!(items.iter().all(|c| c.iter().all(|b| *b == b'a')));
2802 assert!(buf.is_empty());
2803
2804 let (pl, mut buf) = chunked_payload();
2806 buf.extend_from_slice(b"2\r\nab\r\n2\r\ncd\r\n0\r\n\r\n");
2807 assert_eq!(
2808 pl.decode(&mut buf).unwrap(),
2809 Some(PayloadItem::Chunk("abcd".into()))
2810 );
2811 assert_eq!(pl.decode(&mut buf).unwrap(), Some(PayloadItem::Eof));
2812
2813 let (pl, mut buf) = chunked_payload();
2815 buf.extend_from_slice(b"2\r\nab\r\n5\r\ncd");
2816 assert_eq!(
2817 pl.decode(&mut buf).unwrap(),
2818 Some(PayloadItem::Chunk("abcd".into()))
2819 );
2820 assert_eq!(pl.decode(&mut buf).unwrap(), None);
2821 buf.extend_from_slice(b"efg\r\n0\r\n\r\n");
2822 assert_eq!(
2823 pl.decode(&mut buf).unwrap(),
2824 Some(PayloadItem::Chunk("efg".into()))
2825 );
2826 assert_eq!(pl.decode(&mut buf).unwrap(), Some(PayloadItem::Eof));
2827 }
2828
2829 #[test]
2830 fn test_large_chunks_are_not_merged() {
2831 let large = "x".repeat(SMALL_CHUNK);
2832 let (pl, mut buf) = chunked_payload();
2833 buf.extend_from_slice(format!("3\r\nabc\r\n{:X}\r\n{large}\r\n", large.len()).as_bytes());
2834 buf.extend_from_slice(
2835 format!("{:X}\r\n{large}\r\n2\r\nxy\r\n0\r\n\r\n", large.len()).as_bytes(),
2836 );
2837 let range = buf.as_ptr() as usize..buf.as_ptr() as usize + buf.len();
2838
2839 let items = decode_all(&pl, &mut buf);
2840 assert_eq!(
2841 items,
2842 [
2843 Bytes::from("abc"),
2844 large.clone().into(),
2845 large.into(),
2846 "xy".into()
2847 ]
2848 );
2849 assert!(range.contains(&(items[1].as_ptr() as usize)));
2851 assert!(range.contains(&(items[2].as_ptr() as usize)));
2852 }
2853
2854 fn chunked_payload() -> (PayloadDecoder, BytesMut) {
2855 let mut buf = BytesMut::from(
2856 "POST /test HTTP/1.1\r\nhost: localhost\r\ntransfer-encoding: chunked\r\n\r\n",
2857 );
2858 let reader = MessageDecoder::<Request>::default();
2859 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
2860 (pl.unwrap(), buf)
2861 }
2862
2863 #[test]
2864 fn test_chunk_extension_control_chars() {
2865 for line in [
2866 &b"4;a\nX\r\n"[..],
2867 b"4;a=\"\nX\"\r\n",
2868 b"4;a\x00\r\n",
2869 b"4;a\x7f\r\n",
2870 b"4 \n;a\r\n",
2871 ] {
2872 let (pl, mut buf) = chunked_payload();
2873 buf.extend_from_slice(line);
2874 buf.extend_from_slice(b"data\r\n0\r\n\r\n");
2875 assert!(
2876 matches!(pl.decode(&mut buf), Err(DecodeError::InvalidInput(_))),
2877 "{line:?}"
2878 );
2879 }
2880
2881 let (pl, mut buf) = chunked_payload();
2882 buf.extend_from_slice(b"4 ;a=\"b\tc \x80\";d\t\r\ndata\r\n0\r\n\r\n");
2883 let chunk = pl.decode(&mut buf).unwrap().unwrap().chunk();
2884 assert_eq!(chunk, Bytes::from_static(b"data"));
2885 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2886 }
2887
2888 #[test]
2889 fn test_chunk_extensions_limit() {
2890 let (pl, mut buf) = chunked_payload();
2892 buf.extend(b"1;");
2893 let mut failed = false;
2894 for _ in 0..64 {
2895 buf.extend(&[b'a'; 1024]);
2896 match pl.decode(&mut buf) {
2897 Ok(None) => (),
2898 Err(_) => {
2899 failed = true;
2900 break;
2901 }
2902 Ok(Some(item)) => panic!("unexpected item {item:?}"),
2903 }
2904 }
2905 assert!(failed);
2906 assert!(buf.len() <= MAX_CHUNK_EXTENSIONS as usize + 1024 + 20);
2907
2908 let (pl, mut buf) = chunked_payload();
2910 let ext = "a".repeat(1023);
2911 let mut result = Ok(());
2912 for _ in 0..32 {
2913 buf.extend(format!("1;{ext}\r\nx\r\n").as_bytes());
2914 match pl.decode(&mut buf) {
2915 Ok(Some(PayloadItem::Chunk(chunk))) => assert_eq!(chunk, "x"),
2916 Ok(item) => panic!("unexpected item {item:?}"),
2917 Err(err) => {
2918 result = Err(err);
2919 break;
2920 }
2921 }
2922 }
2923 assert!(result.is_err());
2924
2925 let (pl, mut buf) = chunked_payload();
2927 let ext = "a".repeat(MAX_CHUNK_EXTENSIONS as usize - 1);
2928 buf.extend(format!("10;{ext}\r\n0123456789abcdef\r\n0\r\n\r\n").as_bytes());
2929 assert_eq!(
2930 pl.decode(&mut buf).unwrap().unwrap().chunk(),
2931 "0123456789abcdef"
2932 );
2933 assert!(pl.decode(&mut buf).unwrap().unwrap().eof());
2934 }
2935
2936 #[test]
2937 fn test_chunk_framing_errors() {
2938 let (pl, mut buf) = chunked_payload();
2940 buf.extend(b"1;");
2941 buf.extend("a".repeat(MAX_CHUNK_EXTENSIONS as usize + 64).as_bytes());
2942 assert!(matches!(
2943 pl.decode(&mut buf),
2944 Err(DecodeError::InvalidInput("Chunk extensions are too large"))
2945 ));
2946
2947 for (data, msg) in [
2948 (&b"4\r\ndataX\r\n"[..], "Invalid chunk body CR"),
2949 (b"4\r\ndata\rX", "Invalid chunk body LF"),
2950 (b"0\r\n\rX", "Invalid chunk end LF"),
2951 ] {
2952 let (pl, mut buf) = chunked_payload();
2953 buf.extend_from_slice(data);
2954 let mut res = pl.decode(&mut buf);
2955 while let Ok(Some(PayloadItem::Chunk(_))) = res {
2956 res = pl.decode(&mut buf);
2957 }
2958 assert!(
2959 matches!(res, Err(DecodeError::InvalidInput(m)) if m == msg),
2960 "{data:?} {res:?}"
2961 );
2962 }
2963 }
2964
2965 #[test]
2966 fn test_illegal_content_length() {
2967 for value in [&b"12a"[..], b"\xff1"] {
2968 let mut buf = BytesMut::from(&b"GET /test HTTP/1.1\r\ncontent-length: "[..]);
2969 buf.extend_from_slice(value);
2970 buf.extend_from_slice(b"\r\n\r\n");
2971 let reader = MessageDecoder::<Request>::default();
2972 assert!(
2973 matches!(reader.decode(&mut buf), Err(DecodeError::Header)),
2974 "{value:?}"
2975 );
2976 }
2977 }
2978
2979 #[test]
2980 fn test_chunk_size_line_byte_by_byte() {
2981 let feed = |line: &[u8]| {
2982 let (pl, mut buf) = chunked_payload();
2983 let mut data = Vec::new();
2984 for (idx, b) in line.iter().enumerate() {
2985 buf.extend_from_slice(&[*b]);
2986 match pl.decode(&mut buf) {
2987 Ok(None) => (),
2988 Ok(Some(item)) => data.extend_from_slice(&item.chunk()),
2989 Err(_) => return Err(idx),
2990 }
2991 }
2992 Ok(data)
2993 };
2994
2995 for line in [
2997 &b"4;a=b;c\r\ndata"[..],
2998 b"4 \t ;ext\t\x80\r\ndata",
2999 b"4 \r\ndata",
3000 b"4\r\ndata",
3001 ] {
3002 assert_eq!(feed(line).unwrap(), b"data", "{line:?}");
3003 }
3004
3005 for (line, pos) in [
3007 (&b"4;aaaa\x01aaaa\r\n"[..], 6),
3008 (b"4;aa\x7f", 4),
3009 (b"4;aa\ra", 5),
3010 (b"4;aa\na", 4),
3011 (b"4 5", 4),
3012 (b"4 x", 3),
3013 (b"4\rx", 2),
3014 ] {
3015 assert_eq!(feed(line).map(|_| ()), Err(pos), "{line:?}");
3016 }
3017
3018 let mut line = b"10;".to_vec();
3020 line.extend(std::iter::repeat_n(b'a', MAX_CHUNK_EXTENSIONS as usize - 1));
3021 line.extend_from_slice(b"\r\n0123456789abcdef");
3022 assert_eq!(feed(&line).unwrap(), b"0123456789abcdef");
3023
3024 let mut line = b"10;".to_vec();
3025 line.extend(std::iter::repeat_n(b'a', MAX_CHUNK_EXTENSIONS as usize + 1));
3026 line.extend_from_slice(b"\r\n");
3027 assert!(feed(&line).is_err());
3028
3029 let line = vec![b'a'; MAX_CHUNK_EXTENSIONS as usize];
3031 let line = [&b"1;"[..], &line, &line].concat();
3032 assert!(feed(&line).is_err());
3033 }
3034
3035 #[test]
3036 fn test_response_bodyless_status() {
3037 for (head, rest) in [
3038 (
3039 "HTTP/1.1 304 Not Modified\r\ncontent-length: 10\r\n\r\n",
3040 "",
3041 ),
3042 ("HTTP/1.1 204 No Content\r\ncontent-length: 10\r\n\r\n", ""),
3043 (
3044 "HTTP/1.1 204 No Content\r\ntransfer-encoding: chunked\r\n\r\n",
3045 "",
3046 ),
3047 (
3048 "HTTP/1.1 100 Continue\r\ncontent-length: 2\r\n\r\n",
3049 "HTTP/1.1 200 OK\r\n\r\n",
3050 ),
3051 ("HTTP/1.0 304 Not Modified\r\n\r\n", "next"),
3052 ] {
3053 let mut buf = BytesMut::from(format!("{head}{rest}").as_str());
3054 let reader = MessageDecoder::<ResponseHead>::default();
3055 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
3056 assert!(matches!(pl, PayloadType::None), "{head:?}");
3057 assert_eq!(buf, rest.as_bytes(), "{head:?}");
3058 }
3059
3060 let mut buf = BytesMut::from("HTTP/1.1 200 OK\r\ncontent-length: 2\r\n\r\nok");
3061 let reader = MessageDecoder::<ResponseHead>::default();
3062 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
3063 let pl = pl.unwrap();
3064 assert_eq!(
3065 pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
3066 b"ok"
3067 );
3068 }
3069
3070 #[test]
3071 fn test_response_read_until_eof() {
3072 for version in ["1.0", "1.1"] {
3073 let mut buf =
3074 BytesMut::from(format!("HTTP/{version} 200 OK\r\n\r\ntest data").as_str());
3075 let reader = MessageDecoder::<ResponseHead>::default();
3076 let (msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
3077 assert_eq!(msg.connection_type(), ConnectionType::Close, "{version}");
3078 let pl = pl.unwrap();
3079 assert!(pl.is_eof(), "{version}");
3080 let chunk = pl.decode(&mut buf).unwrap().unwrap();
3081 assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"test data")));
3082 }
3083
3084 for version in ["1.0", "1.1"] {
3086 let mut buf = BytesMut::from(
3087 format!("HTTP/{version} 200 OK\r\ncontent-length: 0\r\n\r\n").as_str(),
3088 );
3089 let reader = MessageDecoder::<ResponseHead>::default();
3090 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
3091 assert!(matches!(pl, PayloadType::None), "{version}");
3092 }
3093
3094 let mut buf =
3095 BytesMut::from("HTTP/1.1 101 Switching Protocols\r\ncontent-length: 0\r\n\r\n");
3096 let reader = MessageDecoder::<ResponseHead>::default();
3097 let (_, pl) = reader.decode(&mut buf).unwrap().unwrap();
3098 assert!(matches!(pl, PayloadType::Stream(_)));
3099 }
3100
3101 #[test]
3102 fn test_response_http10_read_until_eof() {
3103 let mut buf = BytesMut::from("HTTP/1.0 200 Ok\r\n\r\ntest data");
3104
3105 let reader = MessageDecoder::<ResponseHead>::default();
3106 let res = reader.decode(&mut buf);
3107 let (_msg, pl) = res.unwrap().unwrap();
3108 let pl = pl.unwrap();
3109
3110 let chunk = pl.decode(&mut buf).unwrap().unwrap();
3111 assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"test data")));
3112 }
3113
3114 #[test]
3115 fn test_multiple_content_length() {
3116 let mut buf = BytesMut::from(
3117 "GET / HTTP/1.1\r\n\
3118 Host: example.com\r\n\
3119 Content-Length: 4\r\n\
3120 Content-Length: 2\r\n\
3121 \r\n\
3122 abcd",
3123 );
3124 expect_parse_err!(&mut buf);
3125
3126 let mut buf = BytesMut::from(
3127 "GET / HTTP/1.1\r\n\
3128 Host: example.com\r\n\
3129 Content-Length: 0\r\n\
3130 Content-Length: 2\r\n\
3131 \r\n\
3132 ab",
3133 );
3134 expect_parse_err!(&mut buf);
3135 }
3136
3137 #[test]
3138 fn test_transfer_encoding_http10() {
3139 let mut buf = BytesMut::from(
3142 "POST / HTTP/1.0\r\n\
3143 Host: example.com\r\n\
3144 Transfer-Encoding: chunked\r\n\
3145 \r\n\
3146 3\r\n\
3147 aaa\r\n\
3148 0\r\n\
3149 ",
3150 );
3151
3152 expect_parse_err!(&mut buf);
3153 }
3154
3155 #[test]
3156 fn test_content_length_and_te_http10() {
3157 let mut buf = BytesMut::from(
3160 "GET / HTTP/1.0\r\n\
3161 Host: example.com\r\n\
3162 Content-Length: 3\r\n\
3163 Transfer-Encoding: chunked\r\n\
3164 \r\n\
3165 000",
3166 );
3167
3168 expect_parse_err!(&mut buf);
3169 }
3170
3171 #[test]
3172 fn test_content_length_plus() {
3173 let mut buf = BytesMut::from(
3174 "GET / HTTP/1.1\r\n\
3175 Host: example.com\r\n\
3176 Content-Length: +3\r\n\
3177 \r\n\
3178 000",
3179 );
3180 expect_parse_err!(&mut buf);
3181 }
3182
3183 #[test]
3184 fn test_unknown_transfer_encoding() {
3185 let mut buf = BytesMut::from(
3186 "GET / HTTP/1.1\r\n\
3187 Host: example.com\r\n\
3188 Transfer-Encoding: JUNK\r\n\
3189 Transfer-Encoding: chunked\r\n\
3190 \r\n\
3191 5\r\n\
3192 hello\r\n\
3193 0",
3194 );
3195
3196 expect_parse_err!(&mut buf);
3197 }
3198
3199 #[test]
3200 fn test_multiple_transfer_encoding() {
3201 let mut buf = BytesMut::from(
3202 "GET / HTTP/1.1\r\n\
3203 Host: example.com\r\n\
3204 Content-Length: 51\r\n\
3205 Transfer-Encoding: identity\r\n\
3206 Transfer-Encoding: chunked\r\n\
3207 \r\n\
3208 0\r\n\
3209 \r\n\
3210 GET /forbidden HTTP/1.1\r\n\
3211 Host: example.com\r\n\r\n",
3212 );
3213 expect_parse_err!(&mut buf);
3214 }
3215
3216 #[test]
3217 fn test_transfer_encoding_content_length_combination() {
3218 let mut buf = BytesMut::from(
3219 "GET /test HTTP/1.1\r\n\
3220 Host: example.com\r\n\
3221 Content-Length: 3\r\n\
3222 Transfer-Encoding: chunked\r\n\
3223 \r\n\
3224 0\r\n",
3225 );
3226 expect_parse_err!(&mut buf);
3227
3228 let mut buf = BytesMut::from(
3229 "GET /test HTTP/1.1\r\n\
3230 Host: example.com\r\n\
3231 Transfer-Encoding: chunked\r\n\
3232 Content-Length: 3\r\n\
3233 \r\n\
3234 0\r\n",
3235 );
3236 expect_parse_err!(&mut buf);
3237 }
3238
3239 #[test]
3240 fn test_transfer_codings() {
3241 for (val, res) in [
3242 ("chunked", Some((true, false))),
3243 (" Chunked ", Some((true, false))),
3244 ("gzip, chunked", Some((true, true))),
3245 ("gzip;q=1 ,, chunked,", Some((true, true))),
3246 ("identity, chunked", Some((true, false))),
3247 ("identity", Some((false, false))),
3248 ("gzip", Some((false, true))),
3249 ("chunked, gzip", Some((false, true))),
3250 ("chunked, chunked", None),
3251 ("chunked, gzip, chunked", None),
3252 ("chunked;a=b", None),
3253 ("gz ip", None),
3254 (";a=b", None),
3255 ] {
3256 assert_eq!(transfer_codings(val.as_bytes()), res, "{val:?}");
3257 }
3258 }
3259
3260 #[test]
3261 fn test_request_transfer_codings() {
3262 for (val, res) in [
3263 ("gzip, chunked", Err(DecodeError::UnsupportedTransferCoding)),
3264 ("chunked, gzip", Err(DecodeError::Header)),
3265 ("gzip", Err(DecodeError::Header)),
3266 ("chunked, chunked", Err(DecodeError::Header)),
3267 ("identity, chunked", Ok(())),
3268 ("chunked,", Ok(())),
3269 ] {
3270 let mut buf = BytesMut::from(
3271 format!("POST / HTTP/1.1\r\nhost: a\r\ntransfer-encoding: {val}\r\n\r\n").as_str(),
3272 );
3273 let reader = MessageDecoder::<Request>::default();
3274 let result = reader.decode(&mut buf).map(|msg| {
3275 let (req, pl) = msg.unwrap();
3276 assert!(req.chunked().unwrap());
3277 assert_eq!(pl, PayloadType::Payload(PayloadDecoder::chunked()));
3278 });
3279 assert_eq!(result, res, "{val:?}");
3280 }
3281 }
3282
3283 #[test]
3284 fn test_response_transfer_codings() {
3285 let mut buf = BytesMut::from(
3287 "HTTP/1.1 200 OK\r\ntransfer-encoding: gzip, chunked\r\n\r\n3\r\nabc\r\n0\r\n\r\n",
3288 );
3289 let reader = MessageDecoder::<ResponseHead>::default();
3290 let (res, pl) = reader.decode(&mut buf).unwrap().unwrap();
3291 assert_eq!(
3292 res.headers.get(header::TRANSFER_ENCODING).unwrap(),
3293 "gzip, chunked"
3294 );
3295 let pl = pl.unwrap();
3296 assert_eq!(
3297 pl.decode(&mut buf).unwrap(),
3298 Some(PayloadItem::Chunk("abc".into()))
3299 );
3300 assert_eq!(pl.decode(&mut buf).unwrap(), Some(PayloadItem::Eof));
3301
3302 for val in ["gzip", "chunked, gzip"] {
3304 let mut buf = BytesMut::from(
3305 format!("HTTP/1.1 200 OK\r\ntransfer-encoding: {val}\r\n\r\n3\r\nabc").as_str(),
3306 );
3307 let (res, pl) = reader.decode(&mut buf).unwrap().unwrap();
3308 assert_eq!(res.connection_type(), ConnectionType::Close, "{val:?}");
3309 let pl = pl.unwrap();
3310 assert!(pl.is_eof(), "{val:?}");
3311 assert_eq!(
3312 pl.decode(&mut buf).unwrap(),
3313 Some(PayloadItem::Chunk("3\r\nabc".into()))
3314 );
3315 }
3316
3317 for hdrs in [
3319 "content-length: 3\r\ntransfer-encoding: gzip\r\n",
3320 "transfer-encoding: gzip\r\ncontent-length: 3\r\n",
3321 "transfer-encoding: gzip, chunked\r\ncontent-length: 3\r\n",
3322 ] {
3323 let mut buf = BytesMut::from(format!("HTTP/1.1 200 OK\r\n{hdrs}\r\nabc").as_str());
3324 let reader = MessageDecoder::<ResponseHead>::default();
3325 assert_eq!(
3326 reader.decode(&mut buf).err(),
3327 Some(DecodeError::Header),
3328 "{hdrs:?}"
3329 );
3330 }
3331 }
3332
3333 #[test]
3334 fn test_transfer_encoding_identity() {
3335 for req in [
3336 "GET /test HTTP/1.1\r\nHost: a\r\n\
3337 Content-Length: 3\r\nTransfer-Encoding: identity\r\n\r\n0\r\n",
3338 "GET /test HTTP/1.1\r\nHost: a\r\n\
3339 Transfer-Encoding: identity\r\nContent-Length: 3\r\n\r\n0\r\n",
3340 "GET /test HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: identity\r\n\r\n",
3341 "GET /test HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: Identity \r\n\r\n",
3342 ] {
3343 let mut buf = BytesMut::from(req);
3344 let reader = MessageDecoder::<Request>::default();
3345 assert_eq!(
3346 reader.decode(&mut buf).err(),
3347 Some(DecodeError::Header),
3348 "{req:?}"
3349 );
3350 }
3351
3352 let mut buf = BytesMut::from(
3354 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\
3355 Transfer-Encoding: identity\r\n\r\n0\r\n",
3356 );
3357 let reader = MessageDecoder::<ResponseHead>::default();
3358 let (_msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
3359 let pl = pl.unwrap();
3360 let chunk = pl.decode(&mut buf).unwrap().unwrap();
3361 assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"0\r\n")));
3362 }
3363
3364 #[test]
3365 fn test_max_headers() {
3366 const TEXT: &str = "GET /test HTTP/1.1\r\n\
3367 Host: example.com\r\n\
3368 Content-Length: 3\r\n\
3369 Test-header: ****\r\n";
3370
3371 const TEXT_2: &str = "GET /test HTTP/1.1\r\n\
3372 Host: example.com\r\n\
3373 Content-Length: 3\r\n\
3374 Test-header: ****\r\n\
3375 \r\n";
3376
3377 let mut buf = BytesMut::from(TEXT);
3378 let cfg: SharedCfg = SharedCfg::new("test")
3379 .add(HttpServiceConfig::new().set_max_buf_size(10))
3380 .into();
3381 let reader = MessageDecoder::<Request>::new(cfg.get());
3382 let err = reader.decode(&mut buf).err().unwrap();
3383 assert_eq!(err, DecodeError::TooLarge(77));
3384
3385 let cfg: SharedCfg = SharedCfg::new("test")
3386 .add(HttpServiceConfig::new().set_max_buf_size(100))
3387 .into();
3388 let reader = MessageDecoder::<Request>::new(cfg.get());
3389 let mut buf = BytesMut::from(TEXT_2);
3391 let res = reader.decode(&mut buf);
3392 assert!(res.is_ok());
3393
3394 let mut buf = BytesMut::from(TEXT);
3396 let res = reader.decode(&mut buf);
3397 assert!(res.is_ok());
3398
3399 let cfg: SharedCfg = SharedCfg::new("test")
3401 .add(HttpServiceConfig::new().set_max_headers(1))
3402 .into();
3403 let reader = MessageDecoder::<Request>::new(cfg.get());
3404 let mut buf = BytesMut::from(TEXT);
3405 let err = reader.decode(&mut buf).err().unwrap();
3406 assert_eq!(err, DecodeError::MaxHeaders);
3407 }
3408
3409 #[test]
3410 fn test_max_headers_repeated_names() {
3411 let cfg: SharedCfg = SharedCfg::new("test")
3412 .add(
3413 HttpServiceConfig::new()
3414 .set_max_headers(2)
3415 .set_host_validation(false),
3416 )
3417 .into();
3418
3419 let reader = MessageDecoder::<Request>::new(cfg.get());
3421 let mut buf = BytesMut::from("GET / HTTP/1.1\r\nX: 1\r\nX: 2\r\nX: 3\r\n\r\n");
3422 assert_eq!(reader.decode(&mut buf).err(), Some(DecodeError::MaxHeaders));
3423
3424 let reader = MessageDecoder::<Request>::new(cfg.get());
3426 let mut buf = BytesMut::from("GET / HTTP/1.1\r\nX: 1\r\nX: 2\r\n");
3427 assert!(reader.decode(&mut buf).unwrap().is_none());
3428 buf.extend_from_slice(b"X: 3\r\n\r\n");
3429 assert_eq!(reader.decode(&mut buf).err(), Some(DecodeError::MaxHeaders));
3430
3431 let reader = MessageDecoder::<Request>::new(cfg.get());
3433 let mut buf = BytesMut::from(
3434 "GET / HTTP/1.1\r\nX: 1\r\nX: 2\r\n\r\nGET / HTTP/1.1\r\nX: 1\r\nX: 2\r\n\r\n",
3435 );
3436 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
3437 assert_eq!(req.headers().get_all("x").count(), 2);
3438 assert!(reader.decode(&mut buf).unwrap().is_some());
3439 }
3440
3441 #[test]
3442 fn test_decoder_reusable_after_error() {
3443 const VALID: &str = "GET /ok HTTP/1.1\r\nHost: example.com\r\n\r\n";
3444
3445 let cfg: SharedCfg = SharedCfg::new("test")
3446 .add(
3447 HttpServiceConfig::new()
3448 .set_max_headers(2)
3449 .set_max_buf_size(128),
3450 )
3451 .into();
3452 let reader = MessageDecoder::<Request>::new(cfg.get());
3453
3454 let invalid = [
3455 "G\x00T / HTTP/1.1\r\n\r\n".to_string(),
3457 "GET / HTTP/1.1\r\nContent-Length: x\r\n\r\n".to_string(),
3459 "GET / HTTP/1.1\r\nA: 1\r\nB: 2\r\nC: 3\r\n".to_string(),
3461 format!("GET / HTTP/1.1\r\nA: {}\r\n", "a".repeat(200)),
3463 ];
3464 for text in invalid {
3465 let mut buf = BytesMut::from(text.as_str());
3466 assert!(reader.decode(&mut buf).is_err(), "{text:?}");
3467
3468 let mut buf = BytesMut::from(VALID);
3469 let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
3470 assert_eq!(req.path(), "/ok");
3471 assert_eq!(req.headers().len(), 1);
3472 }
3473 }
3474
3475 #[test]
3476 fn test_max_buf_size_complete_message() {
3477 const TEXT: &str = "GET /test HTTP/1.1\r\n\
3478 Host: example.com\r\n\
3479 Content-Length: 3\r\n\
3480 Test-header: ****\r\n\
3481 \r\n";
3482
3483 let cfg: SharedCfg = SharedCfg::new("test")
3485 .add(HttpServiceConfig::new().set_max_buf_size(10))
3486 .into();
3487 let reader = MessageDecoder::<Request>::new(cfg.get());
3488 let mut buf = BytesMut::from(TEXT);
3489 let err = reader.decode(&mut buf).err().unwrap();
3490 assert_eq!(err, DecodeError::TooLarge(79));
3491
3492 let cfg: SharedCfg = SharedCfg::new("test")
3494 .add(HttpServiceConfig::new().set_max_buf_size(78))
3495 .into();
3496 let reader = MessageDecoder::<Request>::new(cfg.get());
3497 let mut buf = BytesMut::from(&TEXT[..77]);
3498 assert!(reader.decode(&mut buf).unwrap().is_none());
3499 buf.extend_from_slice(&TEXT.as_bytes()[77..]);
3500 let err = reader.decode(&mut buf).err().unwrap();
3501 assert_eq!(err, DecodeError::TooLarge(79));
3502
3503 let cfg: SharedCfg = SharedCfg::new("test")
3505 .add(HttpServiceConfig::new().set_max_buf_size(100))
3506 .into();
3507 let reader = MessageDecoder::<Request>::new(cfg.get());
3508 let mut buf = BytesMut::from(TEXT);
3509 assert!(reader.decode(&mut buf).unwrap().is_some());
3510
3511 let cfg: SharedCfg = SharedCfg::new("test")
3513 .add(HttpServiceConfig::new().set_max_buf_size(TEXT.len()))
3514 .into();
3515 let reader = MessageDecoder::<Request>::new(cfg.get());
3516 let mut buf = BytesMut::from(TEXT);
3517 assert!(reader.decode(&mut buf).unwrap().is_some());
3518 }
3519}