Skip to main content

ntex/http/h1/
decoder.rs

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
16/// Incoming message decoder
17pub(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    /// number of parsed header lines of the current message
30    headers: u16,
31    /// start line parser, resumed after a partial start line
32    line: T::Parser,
33    line_st: httparse::State,
34}
35
36#[derive(Debug, PartialEq, Eq)]
37/// The payload framing and decoder selected for an incoming HTTP/1 message.
38pub enum PayloadType {
39    /// The message has no payload.
40    None,
41    /// The message has an HTTP body.
42    ///
43    /// Depending on the message headers and version, the decoder may use a
44    /// fixed length, chunked transfer coding, or connection close as the body
45    /// delimiter.
46    Payload(PayloadDecoder),
47    /// The message switches the connection away from HTTP framing.
48    ///
49    /// Subsequent bytes belong to the upgraded protocol or tunnel.
50    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                    // repeated header names count separately
114                    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                    // the parser validates name characters, but not its length
120                    let Ok(name) = HeaderName::from_bytes(&src[n.start..n.end]) else {
121                        return Poll::Ready(Err(DecodeError::Header));
122                    };
123
124                    // name and value are split off `src` directly, without
125                    // splitting the whole line first, `pos` is the number of
126                    // bytes of the line already removed from `src`
127                    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                    // SAFETY: ntex-httparse checks header value for validity
145                    let value = unsafe { HeaderValue::from_shared_unchecked(value) };
146
147                    if let Some(origin) = origin {
148                        // SAFETY: ntex-httparse checks header name validity
149                        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            // start the next message from a clean state
184            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        // leading empty lines are not part of the start line and its size
208        // limit, positions in `line_st` stay valid only while nothing is
209        // removed from `src`
210        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            // the parser resumes from `line_st`, so data of an incomplete
221            // start line is not scanned again on the next read
222            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    /// Returns true if variant is `None`.
294    fn is_none(&self) -> bool {
295        matches!(self, Self::None)
296    }
297
298    #[allow(clippy::borrow_interior_mutable_const)]
299    /// Returns true if variant is represents zero-length (not none) payload.
300    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    /// An upgrade requires both `Upgrade` and the `upgrade` connection option,
341    /// see [RFC 9110 section 7.8](https://www.rfc-editor.org/rfc/rfc9110#section-7.8).
342    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        // https://tools.ietf.org/html/rfc7230#section-3.3.3
354        if self.flags.contains(Flags::CHUNKED) {
355            // Chunked encoding
356            PayloadLength::Payload(PayloadType::Payload(PayloadDecoder::chunked()))
357        } else if let Some(len) = self.content_length
358            // some clients (dart) send "content-length: 0" with websocket upgrade
359            && !(len == 0 && self.flags.contains(Flags::WS_UPGRADE))
360        {
361            // Content-Length
362            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    /// `true` for request messages.
373    const REQUEST: bool;
374
375    /// Resumable start line parser.
376    type Parser: Default;
377
378    fn msg_version(&self) -> Version;
379
380    /// `Expect` and `Upgrade` must be ignored in HTTP/1.0 requests,
381    /// see [RFC 9110 section 10.1.1](https://www.rfc-editor.org/rfc/rfc9110#section-10.1.1)
382    /// and [section 7.8](https://www.rfc-editor.org/rfc/rfc9110#section-7.8).
383    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    /// Decodes the start line, resuming from `st` saved by a previous
390    /// `Pending` result for the same buffer.
391    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                        // accept 0 lengths here and remove them in `decode` after all
427                        // headers have been processed to prevent request smuggling issues
428                        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            // transfer-encoding
440            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                    // a response without final chunked coding is delimited by
458                    // connection close, see https://www.rfc-editor.org/rfc/rfc9112#section-6.3
459                    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            // connection keep-alive state
478            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            // https://www.rfc-editor.org/rfc/rfc9112#section-3.2
486            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                // `Host = uri-host [ ":" port ]`, an empty value is allowed
492                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            // a list of case-insensitive expectations, only `100-continue`
511            // is defined, see RFC 9110 section 10.1.1
512            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                // asterisk-form is only used for a server-wide `OPTIONS` request,
555                // see RFC 9112 section 3.2.4
556                if target == b"*" && method != Method::OPTIONS {
557                    return Err(DecodeError::Uri);
558                }
559                // the target is split off `src` directly, the rest of the
560                // request line is skipped
561                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                    // authority-form is used only, and always, for `CONNECT`, see
566                    // RFC 9112 section 3.2.3
567                    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                    // origin-form, absolute-form or asterisk-form
575                    let asterisk = &target[..] == b"*";
576                    let uri = if target.starts_with(b"//") {
577                        // origin-form path, not a network-path reference
578                        let target = str::from_utf8(&target).map_err(|_| DecodeError::Uri)?;
579                        Url::try_from(format!("/.{target}"))?
580                    } else {
581                        // SAFETY: a valid target is ASCII
582                        let target = unsafe { ByteString::from_bytes_unchecked(target) };
583                        // reuses the buffer if the target is normalized
584                        Url::try_from(target)?
585                    };
586                    let valid = if uri.is_absolute() {
587                        // userinfo is deprecated, see RFC 9110 section 4.2.4
588                        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        // disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
626        // see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
627        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        // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
647        // Protects against some request smuggling attacks.
648        // See https://github.com/actix/actix-web/issues/2767.
649        if length.is_zero() {
650            length = PayloadLength::None;
651        }
652
653        // payload decoder
654        let decoder = match length {
655            PayloadLength::Payload(pl) => pl,
656            PayloadLength::Upgrade => {
657                // upgrade(websocket)
658                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        // `1xx` (except `101`), `204` and `304` responses never have a body,
723        // `Content-Length` of `304` describes the selected representation
724        if is_bodyless(self.status) {
725            return Ok(PayloadType::None);
726        }
727
728        // message payload
729        let decoder = if self.status == StatusCode::SWITCHING_PROTOCOLS
730            && (length.is_zero() || !matches!(length, PayloadLength::Payload(_)))
731        {
732            // switching protocol
733            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            // no declared length, read to eof and close connection
740            // see https://www.rfc-editor.org/rfc/rfc9112#section-6.3
741            self.set_connection_type(ConnectionType::Close);
742            PayloadType::Payload(PayloadDecoder::eof())
743        };
744
745        Ok(decoder)
746    }
747}
748
749/// Parses a `Transfer-Encoding` value.
750///
751/// Returns whether `chunked` is the final transfer coding, and whether other
752/// codings are applied, the obsolete `identity` coding is ignored. `None` if
753/// the value is malformed or `chunked` is applied more than once, see
754/// [RFC 9112 section 6.1](https://www.rfc-editor.org/rfc/rfc9112#section-6.1).
755fn transfer_codings(val: &[u8]) -> Option<(bool, bool)> {
756    let mut chunked = false;
757    let mut seen_chunked = false;
758    let mut other = false;
759    // empty list elements are allowed, see RFC 9110 section 5.6.1
760    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            // chunked has no parameters
771            if seen_chunked || name.len() != coding.len() {
772                return None;
773            }
774            chunked = true;
775            seen_chunked = true;
776        } else if chunked {
777            // chunked is not the final coding
778            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)]
803/// A decoded HTTP/1 payload item.
804pub enum PayloadItem {
805    /// A payload data chunk.
806    Chunk(Bytes),
807    /// Trailer fields of a chunked payload, [`PayloadItem::Eof`] follows.
808    Trailers(HeaderMap),
809    /// The end of the payload.
810    Eof,
811}
812
813/// Incremental decoder for an HTTP/1 message body.
814///
815/// The decoder handles fixed `Content-Length`, chunked transfer coding, and
816/// bodies delimited by connection EOF. It implements [`Decoder`] and retains
817/// framing state between calls.
818///
819/// Fixed-length and chunked decoders emit [`PayloadItem::Eof`] when their wire
820/// framing completes. An EOF-delimited decoder emits every available byte as a
821/// chunk but cannot infer completion from an empty input buffer; the transport
822/// owner must treat connection closure as the end of that payload.
823///
824/// `Ok(None)` means that more bytes or transport EOF are required. A
825/// [`DecodeError`] reports malformed payload framing, such as an invalid
826/// chunk-size or chunk terminator. Cloning preserves the current payload
827/// framing state.
828///
829/// Chunk extensions are validated and skipped. Trailer fields are buffered
830/// until the trailer section is complete and emitted as
831/// [`PayloadItem::Trailers`]. A chunked payload is rejected with
832/// [`DecodeError::InvalidInput`] if its chunk extensions exceed 16 KiB in
833/// total, or if its trailer section, including line terminators, exceeds
834/// 4 KiB.
835#[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    /// Returns `true` if the payload is delimited by connection close.
866    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    /// A Reader used when a Content-Length header is passed with a positive
874    /// integer.
875    Length(u64),
876    /// A Reader used when Transfer-Encoding is `chunked`.
877    ///
878    /// Holds the chunked state, the remaining size of the current chunk and
879    /// the size limits.
880    Chunked(ChunkedState, u64, ChunkedLimits),
881    /// A Reader used for responses that don't indicate a length or chunked.
882    ///
883    /// Note: This should only used for `Response`s. It is illegal for a
884    /// `Request` to be made with both `Content-Length` and
885    /// `Transfer-Encoding: chunked` missing, as explained from the spec:
886    ///
887    /// > If a Transfer-Encoding header field is present in a response and
888    /// > the chunked transfer coding is not the final encoding, the
889    /// > message body length is determined by reading the connection until
890    /// > it is closed by the server.  If a Transfer-Encoding header field
891    /// > is present in a request and the chunked transfer coding is not
892    /// > the final encoding, the message body length cannot be determined
893    /// > reliably; the server MUST respond with the 400 (Bad Request)
894    /// > status code and then close the connection.
895    Eof,
896}
897
898/// Maximum number of chunk-size line bytes beyond the size digits, such as
899/// chunk extensions, accepted for a chunked payload.
900const MAX_CHUNK_EXTENSIONS: u32 = 16 * 1024;
901
902/// Maximum size of the trailer section, including line terminators, accepted
903/// for a chunked payload.
904const MAX_CHUNK_TRAILERS: u32 = 4 * 1024;
905
906/// Chunks smaller than this are merged with the following chunks.
907const SMALL_CHUNK: usize = 1024;
908
909/// Maximum size of merged chunks.
910const MAX_MERGED_CHUNKS: usize = 16 * 1024;
911
912#[derive(Debug, Copy, Clone, PartialEq, Eq)]
913struct ChunkedLimits {
914    /// chunk-size line bytes beyond the size digits received so far
915    ext: u32,
916    /// trailer section bytes of complete field lines, they are validated
917    trailers: u32,
918    /// bytes of a partially received chunk-size line that are validated
919    line: u32,
920    /// parser state at the end of the validated bytes
921    line_state: SizeLine,
922}
923
924/// Parser state of a partially received chunk-size line.
925#[derive(Debug, Copy, Clone, PartialEq, Eq)]
926enum SizeLine {
927    /// the line must be parsed from the start
928    Unknown,
929    /// whitespace after the chunk size
930    Lws,
931    /// chunk extensions
932    Ext,
933}
934
935impl SizeLine {
936    /// Returns `true` if bytes do not change the parser state.
937    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            // any octet except control characters other than HTAB, `\r` ends the line
942            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                // small chunks are merged into one item, the payload of tiny
992                // chunks would be buffered as many items
993                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                    // a large chunk is not copied into merged chunks
998                    if *state == ChunkedState::Body && *size >= SMALL_CHUNK as u64 && data.is_some()
999                    {
1000                        break Ok(None);
1001                    }
1002                    // data is returned before trailers
1003                    if *state == ChunkedState::Trailers && data.is_some() {
1004                        break Ok(None);
1005                    }
1006
1007                    let mut buf = None;
1008                    // advances the chunked state
1009                    *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                // the end of the payload is reported on the next call
1050                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    /// Reads a chunk-size line.
1103    ///
1104    /// Bytes beyond the size digits, chunk extensions and whitespace, are
1105    /// ignored but count against [`MAX_CHUNK_EXTENSIONS`] for the whole
1106    /// payload, which also bounds a partially received line.
1107    fn read_size(
1108        rdr: &mut BytesMut,
1109        size: &mut u64,
1110        limits: &mut ChunkedLimits,
1111    ) -> Poll<Result<ChunkedState, DecodeError>> {
1112        // at most 16 size digits and CRLF
1113        let max = (MAX_CHUNK_EXTENSIONS - limits.ext) as usize + 18;
1114
1115        // bytes of a partial line are validated once, new bytes that do
1116        // not change the parser state do not need to parse the line again
1117        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                // the line ends with CRLF
1136                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                    // `\n` must follow
1159                    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            // trailer field, must start with a field name character
1225            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    /// Reads the trailer section, it is buffered until the section is complete.
1231    ///
1232    /// Field lines, including line terminators, count against
1233    /// [`MAX_CHUNK_TRAILERS`]. Complete field lines are validated once.
1234    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                // the end of the trailer section
1246                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            // a field line
1272            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        // an incomplete field line
1296        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
1311/// Returns the length of complete empty lines at the start of `buf`.
1312fn 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
1323/// Splits a trailer field line into its name and value.
1324fn 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
1335/// Checks for a `tchar`, see [RFC 9110 section 5.6.2](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.2).
1336fn 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    /// Asterisk-form is only valid for `OPTIONS`, RFC 9112 section 3.2.4.
1393    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        // userinfo is rejected in absolute-form
1419        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        // the partial name stays within the buffer limit
1506        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        // an invalid byte is rejected without waiting for the line end
1520        buf.extend_from_slice(b"\x01");
1521        assert!(reader.decode(&mut buf).is_err());
1522
1523        // the decoder starts over after an error
1524        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        // byte by byte
1528        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        // partial start lines of different connections on one thread
1550        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        // empty lines count towards the buffer limit
1578        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        // the limit includes the line end
1601        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        // incomplete line
1615        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        // headers are not limited
1627        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        // default limit
1634        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        // tokens past the first 5 bytes
1690        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        // `close` in an earlier header is not overridden by a later one
1714        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        // request
1748        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        // response
1773        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        // transfer-encoding is not supported for http1.0
1914        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            // the next request is not consumed as upgraded stream
2188            let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2189            assert_eq!(req.path(), "/next");
2190        }
2191
2192        // a body is not treated as an upgraded stream
2193        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        // both are present
2203        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        // the headers are still available
2252        assert_eq!(req.headers().get(header::UPGRADE).unwrap(), "websocket");
2253        assert_eq!(req.headers().get(header::EXPECT).unwrap(), "100-continue");
2254        // the next request is not consumed as upgraded stream
2255        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
2256        assert_eq!(req.path(), "/next");
2257
2258        // HTTP/1.1 is not affected
2259        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        // validation can be disabled
2319        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        // responses are not affected
2332        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        // typo in chunked
2363        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        // zero content-length is ignored regardless of header order
2436        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        // non-zero content-length delimits the body regardless of header order
2452        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        // duplicate content-length is rejected even after websocket upgrade
2472        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        // a single field
2629        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            // an endless field line
2640            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        // many small fields
2650        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        // trailers split across reads
2686        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        // invalid trailers
2716        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"); // test: test\r\n\r\n")
2766        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        // merged chunks are returned before the end of the payload
2805        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        // incomplete chunk
2814        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        // large chunks are not copied
2850        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        // a size line that never ends is not buffered without limit
2891        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        // extensions are limited for the whole payload
2909        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        // extensions up to the limit are accepted
2926        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        // a partial size line larger than the limit, received at once
2939        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        // valid lines
2996        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        // invalid lines fail at the invalid byte
3006        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        // long extension fed byte by byte
3019        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        // a line that never ends fails at the limit
3030        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        // zero content-length has no payload
3085        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        // in HTTP/1.0 transfer encoding is not supported
3140
3141        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        // in HTTP/1.0 transfer encoding is not supported
3158
3159        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        // final chunked coding frames the payload, other codings are not decoded
3286        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        // without final chunked coding the payload is delimited by connection close
3303        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        // codings with Content-Length are rejected in either order
3318        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        // responses are tolerated
3353        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        // decode one message
3390        let mut buf = BytesMut::from(TEXT_2);
3391        let res = reader.decode(&mut buf);
3392        assert!(res.is_ok());
3393
3394        // decode second message, same decoder
3395        let mut buf = BytesMut::from(TEXT);
3396        let res = reader.decode(&mut buf);
3397        assert!(res.is_ok());
3398
3399        // MAX HEADERS
3400        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        // repeated names count separately
3420        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        // count is kept across partial reads
3425        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        // count is reset for the next message
3432        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            // request line
3456            "G\x00T / HTTP/1.1\r\n\r\n".to_string(),
3457            // header
3458            "GET / HTTP/1.1\r\nContent-Length: x\r\n\r\n".to_string(),
3459            // partial head followed by too many headers
3460            "GET / HTTP/1.1\r\nA: 1\r\nB: 2\r\nC: 3\r\n".to_string(),
3461            // message head is too large
3462            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        // whole message head is available in one buffer
3484        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        // message head completes on the second read
3493        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        // message head size is within the limit
3504        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        // the configured maximum is inclusive
3512        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}