actix_http/h1/
decoder.rs

1use std::{io, marker::PhantomData, mem::MaybeUninit, task::Poll};
2
3use actix_codec::Decoder;
4use bytes::{Bytes, BytesMut};
5use http::{
6    header::{self, HeaderName, HeaderValue},
7    Method, StatusCode, Uri, Version,
8};
9use tracing::{debug, error, trace};
10
11use super::chunked::ChunkedState;
12use crate::{error::ParseError, header::HeaderMap, ConnectionType, Request, ResponseHead};
13
14pub(crate) const MAX_BUFFER_SIZE: usize = 131_072;
15const MAX_HEADERS: usize = 96;
16
17/// Incoming message decoder
18pub(crate) struct MessageDecoder<T: MessageType>(PhantomData<T>);
19
20#[derive(Debug)]
21/// Incoming request type
22pub(crate) enum PayloadType {
23    None,
24    Payload(PayloadDecoder),
25    Stream(PayloadDecoder),
26}
27
28impl<T: MessageType> Default for MessageDecoder<T> {
29    fn default() -> Self {
30        MessageDecoder(PhantomData)
31    }
32}
33
34impl<T: MessageType> Decoder for MessageDecoder<T> {
35    type Item = (T, PayloadType);
36    type Error = ParseError;
37
38    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
39        T::decode(src)
40    }
41}
42
43pub(crate) enum PayloadLength {
44    Payload(PayloadType),
45    UpgradeWebSocket,
46    None,
47}
48
49impl PayloadLength {
50    /// Returns true if variant is `None`.
51    fn is_none(&self) -> bool {
52        matches!(self, Self::None)
53    }
54
55    /// Returns true if variant is represents zero-length (not none) payload.
56    fn is_zero(&self) -> bool {
57        matches!(
58            self,
59            PayloadLength::Payload(PayloadType::Payload(PayloadDecoder {
60                kind: Kind::Length(0)
61            }))
62        )
63    }
64}
65
66pub(crate) trait MessageType: Sized {
67    fn set_connection_type(&mut self, conn_type: Option<ConnectionType>);
68
69    fn set_expect(&mut self);
70
71    fn headers_mut(&mut self) -> &mut HeaderMap;
72
73    fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError>;
74
75    fn set_headers(
76        &mut self,
77        slice: &Bytes,
78        raw_headers: &[HeaderIndex],
79        version: Version,
80    ) -> Result<PayloadLength, ParseError> {
81        let mut ka = None;
82        let mut has_upgrade_websocket = false;
83        let mut expect = false;
84        let mut chunked = false;
85        let mut seen_te = false;
86        let mut content_length = None;
87
88        {
89            let headers = self.headers_mut();
90
91            for idx in raw_headers.iter() {
92                let name = HeaderName::from_bytes(&slice[idx.name.0..idx.name.1]).unwrap();
93
94                // SAFETY: httparse already checks header value is only visible ASCII bytes
95                // from_maybe_shared_unchecked contains debug assertions so they are omitted here
96                let value = unsafe {
97                    HeaderValue::from_maybe_shared_unchecked(slice.slice(idx.value.0..idx.value.1))
98                };
99
100                match name {
101                    header::CONTENT_LENGTH if content_length.is_some() => {
102                        debug!("multiple Content-Length");
103                        return Err(ParseError::Header);
104                    }
105
106                    header::CONTENT_LENGTH => match value.to_str().map(str::trim) {
107                        Ok(val) if val.starts_with('+') => {
108                            debug!("illegal Content-Length: {:?}", val);
109                            return Err(ParseError::Header);
110                        }
111
112                        Ok(val) => {
113                            if let Ok(len) = val.parse::<u64>() {
114                                // accept 0 lengths here and remove them in `decode` after all
115                                // headers have been processed to prevent request smuggling issues
116                                content_length = Some(len);
117                            } else {
118                                debug!("illegal Content-Length: {:?}", val);
119                                return Err(ParseError::Header);
120                            }
121                        }
122
123                        Err(_) => {
124                            debug!("illegal Content-Length: {:?}", value);
125                            return Err(ParseError::Header);
126                        }
127                    },
128
129                    // transfer-encoding
130                    header::TRANSFER_ENCODING if seen_te => {
131                        debug!("multiple Transfer-Encoding not allowed");
132                        return Err(ParseError::Header);
133                    }
134
135                    header::TRANSFER_ENCODING if version == Version::HTTP_11 => {
136                        seen_te = true;
137
138                        if let Ok(val) = value.to_str().map(str::trim) {
139                            if val.eq_ignore_ascii_case("chunked") {
140                                chunked = true;
141                            } else if val.eq_ignore_ascii_case("identity") {
142                                // allow silently since multiple TE headers are already checked
143                            } else {
144                                debug!("illegal Transfer-Encoding: {:?}", val);
145                                return Err(ParseError::Header);
146                            }
147                        } else {
148                            return Err(ParseError::Header);
149                        }
150                    }
151
152                    // connection keep-alive state
153                    header::CONNECTION => {
154                        ka = if let Ok(conn) = value.to_str().map(str::trim) {
155                            if conn.eq_ignore_ascii_case("keep-alive") {
156                                Some(ConnectionType::KeepAlive)
157                            } else if conn.eq_ignore_ascii_case("close") {
158                                Some(ConnectionType::Close)
159                            } else if conn.eq_ignore_ascii_case("upgrade") {
160                                Some(ConnectionType::Upgrade)
161                            } else {
162                                None
163                            }
164                        } else {
165                            None
166                        };
167                    }
168
169                    header::UPGRADE => {
170                        if let Ok(val) = value.to_str().map(str::trim) {
171                            if val.eq_ignore_ascii_case("websocket") {
172                                has_upgrade_websocket = true;
173                            }
174                        }
175                    }
176
177                    header::EXPECT => {
178                        let bytes = value.as_bytes();
179                        if bytes.len() >= 4 && &bytes[0..4] == b"100-" {
180                            expect = true;
181                        }
182                    }
183
184                    _ => {}
185                }
186
187                headers.append(name, value);
188            }
189        }
190
191        self.set_connection_type(ka);
192
193        if expect {
194            self.set_expect()
195        }
196
197        // https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
198        if chunked {
199            // Chunked encoding
200            Ok(PayloadLength::Payload(PayloadType::Payload(
201                PayloadDecoder::chunked(),
202            )))
203        } else if has_upgrade_websocket {
204            Ok(PayloadLength::UpgradeWebSocket)
205        } else if let Some(len) = content_length {
206            // Content-Length
207            Ok(PayloadLength::Payload(PayloadType::Payload(
208                PayloadDecoder::length(len),
209            )))
210        } else {
211            Ok(PayloadLength::None)
212        }
213    }
214}
215
216impl MessageType for Request {
217    fn set_connection_type(&mut self, conn_type: Option<ConnectionType>) {
218        if let Some(ctype) = conn_type {
219            self.head_mut().set_connection_type(ctype);
220        }
221    }
222
223    fn set_expect(&mut self) {
224        self.head_mut().set_expect();
225    }
226
227    fn headers_mut(&mut self) -> &mut HeaderMap {
228        &mut self.head_mut().headers
229    }
230
231    fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError> {
232        let mut headers: [HeaderIndex; MAX_HEADERS] = EMPTY_HEADER_INDEX_ARRAY;
233
234        let (len, method, uri, ver, h_len) = {
235            // SAFETY:
236            // Create an uninitialized array of `MaybeUninit`. The `assume_init` is safe because the
237            // type we are claiming to have initialized here is a bunch of `MaybeUninit`s, which
238            // do not require initialization.
239            let mut parsed = unsafe {
240                MaybeUninit::<[MaybeUninit<httparse::Header<'_>>; MAX_HEADERS]>::uninit()
241                    .assume_init()
242            };
243
244            let mut req = httparse::Request::new(&mut []);
245
246            match req.parse_with_uninit_headers(src, &mut parsed)? {
247                httparse::Status::Complete(len) => {
248                    let method = Method::from_bytes(req.method.unwrap().as_bytes())
249                        .map_err(|_| ParseError::Method)?;
250                    let uri = Uri::try_from(req.path.unwrap())?;
251                    let version = if req.version.unwrap() == 1 {
252                        Version::HTTP_11
253                    } else {
254                        Version::HTTP_10
255                    };
256                    HeaderIndex::record(src, req.headers, &mut headers);
257
258                    (len, method, uri, version, req.headers.len())
259                }
260
261                httparse::Status::Partial => {
262                    return if src.len() >= MAX_BUFFER_SIZE {
263                        trace!("MAX_BUFFER_SIZE unprocessed data reached, closing");
264                        Err(ParseError::TooLarge)
265                    } else {
266                        // Return None to notify more read are needed for parsing request
267                        Ok(None)
268                    };
269                }
270            }
271        };
272
273        let mut msg = Request::new();
274
275        // convert headers
276        let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
277
278        // disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
279        // see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
280        if ver == Version::HTTP_10 && method == Method::POST && length.is_none() {
281            debug!("no Content-Length specified for HTTP/1.0 POST request");
282            return Err(ParseError::Header);
283        }
284
285        // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
286        // Protects against some request smuggling attacks.
287        // See https://github.com/actix/actix-web/issues/2767.
288        if length.is_zero() {
289            length = PayloadLength::None;
290        }
291
292        // payload decoder
293        let decoder = match length {
294            PayloadLength::Payload(pl) => pl,
295            PayloadLength::UpgradeWebSocket => {
296                // upgrade (WebSocket)
297                PayloadType::Stream(PayloadDecoder::eof())
298            }
299            PayloadLength::None => {
300                if method == Method::CONNECT {
301                    PayloadType::Stream(PayloadDecoder::eof())
302                } else {
303                    PayloadType::None
304                }
305            }
306        };
307
308        let head = msg.head_mut();
309        head.uri = uri;
310        head.method = method;
311        head.version = ver;
312
313        Ok(Some((msg, decoder)))
314    }
315}
316
317impl MessageType for ResponseHead {
318    fn set_connection_type(&mut self, conn_type: Option<ConnectionType>) {
319        if let Some(ctype) = conn_type {
320            ResponseHead::set_connection_type(self, ctype);
321        }
322    }
323
324    fn set_expect(&mut self) {}
325
326    fn headers_mut(&mut self) -> &mut HeaderMap {
327        &mut self.headers
328    }
329
330    fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError> {
331        let mut headers: [HeaderIndex; MAX_HEADERS] = EMPTY_HEADER_INDEX_ARRAY;
332
333        let (len, ver, status, h_len) = {
334            // SAFETY:
335            // Create an uninitialized array of `MaybeUninit`. The `assume_init` is safe because the
336            // type we are claiming to have initialized here is a bunch of `MaybeUninit`s, which
337            // do not require initialization.
338            let mut parsed = unsafe {
339                MaybeUninit::<[MaybeUninit<httparse::Header<'_>>; MAX_HEADERS]>::uninit()
340                    .assume_init()
341            };
342
343            let mut res = httparse::Response::new(&mut []);
344
345            let mut config = httparse::ParserConfig::default();
346            config.allow_spaces_after_header_name_in_responses(true);
347
348            match config.parse_response_with_uninit_headers(&mut res, src, &mut parsed)? {
349                httparse::Status::Complete(len) => {
350                    let version = if res.version.unwrap() == 1 {
351                        Version::HTTP_11
352                    } else {
353                        Version::HTTP_10
354                    };
355
356                    let status =
357                        StatusCode::from_u16(res.code.unwrap()).map_err(|_| ParseError::Status)?;
358                    HeaderIndex::record(src, res.headers, &mut headers);
359
360                    (len, version, status, res.headers.len())
361                }
362
363                httparse::Status::Partial => {
364                    return if src.len() >= MAX_BUFFER_SIZE {
365                        error!("MAX_BUFFER_SIZE unprocessed data reached, closing");
366                        Err(ParseError::TooLarge)
367                    } else {
368                        Ok(None)
369                    }
370                }
371            }
372        };
373
374        let mut msg = ResponseHead::new(status);
375        msg.version = ver;
376
377        // convert headers
378        let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
379
380        // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
381        // Protects against some request smuggling attacks.
382        // See https://github.com/actix/actix-web/issues/2767.
383        if length.is_zero() {
384            length = PayloadLength::None;
385        }
386
387        // message payload
388        let decoder = if let PayloadLength::Payload(pl) = length {
389            pl
390        } else if status == StatusCode::SWITCHING_PROTOCOLS {
391            // switching protocol or connect
392            PayloadType::Stream(PayloadDecoder::eof())
393        } else {
394            // for HTTP/1.0 read to eof and close connection
395            if msg.version == Version::HTTP_10 {
396                msg.set_connection_type(ConnectionType::Close);
397                PayloadType::Payload(PayloadDecoder::eof())
398            } else {
399                PayloadType::None
400            }
401        };
402
403        Ok(Some((msg, decoder)))
404    }
405}
406
407#[derive(Clone, Copy)]
408pub(crate) struct HeaderIndex {
409    pub(crate) name: (usize, usize),
410    pub(crate) value: (usize, usize),
411}
412
413pub(crate) const EMPTY_HEADER_INDEX: HeaderIndex = HeaderIndex {
414    name: (0, 0),
415    value: (0, 0),
416};
417
418pub(crate) const EMPTY_HEADER_INDEX_ARRAY: [HeaderIndex; MAX_HEADERS] =
419    [EMPTY_HEADER_INDEX; MAX_HEADERS];
420
421impl HeaderIndex {
422    pub(crate) fn record(
423        bytes: &[u8],
424        headers: &[httparse::Header<'_>],
425        indices: &mut [HeaderIndex],
426    ) {
427        let bytes_ptr = bytes.as_ptr() as usize;
428        for (header, indices) in headers.iter().zip(indices.iter_mut()) {
429            let name_start = header.name.as_ptr() as usize - bytes_ptr;
430            let name_end = name_start + header.name.len();
431            indices.name = (name_start, name_end);
432            let value_start = header.value.as_ptr() as usize - bytes_ptr;
433            let value_end = value_start + header.value.len();
434            indices.value = (value_start, value_end);
435        }
436    }
437}
438
439#[derive(Debug, Clone, PartialEq, Eq)]
440/// Chunk type yielded while decoding a payload.
441pub enum PayloadItem {
442    Chunk(Bytes),
443    Eof,
444}
445
446/// Decoder that can handle different payload types.
447///
448/// If a message body does not use `Transfer-Encoding`, it should include a `Content-Length`.
449#[derive(Debug, Clone, PartialEq, Eq)]
450pub struct PayloadDecoder {
451    kind: Kind,
452}
453
454impl PayloadDecoder {
455    /// Constructs a fixed-length payload decoder.
456    pub fn length(x: u64) -> PayloadDecoder {
457        PayloadDecoder {
458            kind: Kind::Length(x),
459        }
460    }
461
462    /// Constructs a chunked encoding decoder.
463    pub fn chunked() -> PayloadDecoder {
464        PayloadDecoder {
465            kind: Kind::Chunked(ChunkedState::Size, 0),
466        }
467    }
468
469    /// Creates an decoder that yields chunks until the stream returns EOF.
470    pub fn eof() -> PayloadDecoder {
471        PayloadDecoder { kind: Kind::Eof }
472    }
473}
474
475#[derive(Debug, Clone, PartialEq, Eq)]
476enum Kind {
477    /// A reader used when a `Content-Length` header is passed with a positive integer.
478    Length(u64),
479
480    /// A reader used when `Transfer-Encoding` is `chunked`.
481    Chunked(ChunkedState, u64),
482
483    /// A reader used for responses that don't indicate a length or chunked.
484    ///
485    /// Note: This should only used for `Response`s. It is illegal for a `Request` to be made
486    /// without either of `Content-Length` and `Transfer-Encoding: chunked` missing, as explained
487    /// in [RFC 7230 §3.3.3]:
488    ///
489    /// > If a Transfer-Encoding header field is present in a response and the chunked transfer
490    /// > coding is not the final encoding, the message body length is determined by reading the
491    /// > connection until it is closed by the server. If a Transfer-Encoding header field is
492    /// > present in a request and the chunked transfer coding is not the final encoding, the
493    /// > message body length cannot be determined reliably; the server MUST respond with the 400
494    /// > (Bad Request) status code and then close the connection.
495    ///
496    /// [RFC 7230 §3.3.3]: https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
497    Eof,
498}
499
500impl Decoder for PayloadDecoder {
501    type Item = PayloadItem;
502    type Error = io::Error;
503
504    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
505        match self.kind {
506            Kind::Length(ref mut remaining) => {
507                if *remaining == 0 {
508                    Ok(Some(PayloadItem::Eof))
509                } else {
510                    if src.is_empty() {
511                        return Ok(None);
512                    }
513                    let len = src.len() as u64;
514                    let buf;
515                    if *remaining > len {
516                        buf = src.split().freeze();
517                        *remaining -= len;
518                    } else {
519                        buf = src.split_to(*remaining as usize).freeze();
520                        *remaining = 0;
521                    };
522                    trace!("Length read: {}", buf.len());
523                    Ok(Some(PayloadItem::Chunk(buf)))
524                }
525            }
526
527            Kind::Chunked(ref mut state, ref mut size) => {
528                loop {
529                    let mut buf = None;
530
531                    // advances the chunked state
532                    *state = match state.step(src, size, &mut buf) {
533                        Poll::Pending => return Ok(None),
534                        Poll::Ready(Ok(state)) => state,
535                        Poll::Ready(Err(err)) => return Err(err),
536                    };
537
538                    if *state == ChunkedState::End {
539                        trace!("End of chunked stream");
540                        return Ok(Some(PayloadItem::Eof));
541                    }
542
543                    if let Some(buf) = buf {
544                        return Ok(Some(PayloadItem::Chunk(buf)));
545                    }
546
547                    if src.is_empty() {
548                        return Ok(None);
549                    }
550                }
551            }
552
553            Kind::Eof => {
554                if src.is_empty() {
555                    Ok(None)
556                } else {
557                    Ok(Some(PayloadItem::Chunk(src.split().freeze())))
558                }
559            }
560        }
561    }
562}
563
564#[cfg(test)]
565mod tests {
566    use super::*;
567    use crate::{header::SET_COOKIE, HttpMessage as _};
568
569    impl PayloadType {
570        pub(crate) fn unwrap(self) -> PayloadDecoder {
571            match self {
572                PayloadType::Payload(pl) => pl,
573                _ => panic!(),
574            }
575        }
576
577        pub(crate) fn is_unhandled(&self) -> bool {
578            matches!(self, PayloadType::Stream(_))
579        }
580    }
581
582    impl PayloadItem {
583        pub(crate) fn chunk(self) -> Bytes {
584            match self {
585                PayloadItem::Chunk(chunk) => chunk,
586                _ => panic!("error"),
587            }
588        }
589
590        pub(crate) fn eof(&self) -> bool {
591            matches!(*self, PayloadItem::Eof)
592        }
593    }
594
595    macro_rules! parse_ready {
596        ($e:expr) => {{
597            match MessageDecoder::<Request>::default().decode($e) {
598                Ok(Some((msg, _))) => msg,
599                Ok(_) => unreachable!("Eof during parsing http request"),
600                Err(err) => unreachable!("Error during parsing http request: {:?}", err),
601            }
602        }};
603    }
604
605    macro_rules! expect_parse_err {
606        ($e:expr) => {{
607            match MessageDecoder::<Request>::default().decode($e) {
608                Err(err) => match err {
609                    ParseError::Io(_) => unreachable!("Parse error expected"),
610                    _ => {}
611                },
612                _ => unreachable!("Error expected"),
613            }
614        }};
615    }
616
617    #[test]
618    fn test_parse() {
619        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n\r\n");
620
621        let mut reader = MessageDecoder::<Request>::default();
622        match reader.decode(&mut buf) {
623            Ok(Some((req, _))) => {
624                assert_eq!(req.version(), Version::HTTP_11);
625                assert_eq!(*req.method(), Method::GET);
626                assert_eq!(req.path(), "/test");
627            }
628            Ok(_) | Err(_) => unreachable!("Error during parsing http request"),
629        }
630    }
631
632    #[test]
633    fn test_parse_partial() {
634        let mut buf = BytesMut::from("PUT /test HTTP/1");
635
636        let mut reader = MessageDecoder::<Request>::default();
637        assert!(reader.decode(&mut buf).unwrap().is_none());
638
639        buf.extend(b".1\r\n\r\n");
640        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
641        assert_eq!(req.version(), Version::HTTP_11);
642        assert_eq!(*req.method(), Method::PUT);
643        assert_eq!(req.path(), "/test");
644    }
645
646    #[test]
647    fn parse_h09_reject() {
648        let mut buf = BytesMut::from(
649            "GET /test1 HTTP/0.9\r\n\
650            \r\n",
651        );
652
653        let mut reader = MessageDecoder::<Request>::default();
654        reader.decode(&mut buf).unwrap_err();
655
656        let mut buf = BytesMut::from(
657            "POST /test2 HTTP/0.9\r\n\
658            Content-Length: 3\r\n\
659            \r\n
660            abc",
661        );
662
663        let mut reader = MessageDecoder::<Request>::default();
664        reader.decode(&mut buf).unwrap_err();
665    }
666
667    #[test]
668    fn parse_h10_get() {
669        let mut buf = BytesMut::from(
670            "GET /test1 HTTP/1.0\r\n\
671            \r\n",
672        );
673
674        let mut reader = MessageDecoder::<Request>::default();
675        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
676        assert_eq!(req.version(), Version::HTTP_10);
677        assert_eq!(*req.method(), Method::GET);
678        assert_eq!(req.path(), "/test1");
679
680        let mut buf = BytesMut::from(
681            "GET /test2 HTTP/1.0\r\n\
682            Content-Length: 0\r\n\
683            \r\n",
684        );
685
686        let mut reader = MessageDecoder::<Request>::default();
687        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
688        assert_eq!(req.version(), Version::HTTP_10);
689        assert_eq!(*req.method(), Method::GET);
690        assert_eq!(req.path(), "/test2");
691
692        let mut buf = BytesMut::from(
693            "GET /test3 HTTP/1.0\r\n\
694            Content-Length: 3\r\n\
695            \r\n
696            abc",
697        );
698
699        let mut reader = MessageDecoder::<Request>::default();
700        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
701        assert_eq!(req.version(), Version::HTTP_10);
702        assert_eq!(*req.method(), Method::GET);
703        assert_eq!(req.path(), "/test3");
704    }
705
706    #[test]
707    fn parse_h10_post() {
708        let mut buf = BytesMut::from(
709            "POST /test1 HTTP/1.0\r\n\
710            Content-Length: 3\r\n\
711            \r\n\
712            abc",
713        );
714
715        let mut reader = MessageDecoder::<Request>::default();
716        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
717        assert_eq!(req.version(), Version::HTTP_10);
718        assert_eq!(*req.method(), Method::POST);
719        assert_eq!(req.path(), "/test1");
720
721        let mut buf = BytesMut::from(
722            "POST /test2 HTTP/1.0\r\n\
723            Content-Length: 0\r\n\
724            \r\n",
725        );
726
727        let mut reader = MessageDecoder::<Request>::default();
728        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
729        assert_eq!(req.version(), Version::HTTP_10);
730        assert_eq!(*req.method(), Method::POST);
731        assert_eq!(req.path(), "/test2");
732
733        let mut buf = BytesMut::from(
734            "POST /test3 HTTP/1.0\r\n\
735            \r\n",
736        );
737
738        let mut reader = MessageDecoder::<Request>::default();
739        let err = reader.decode(&mut buf).unwrap_err();
740        assert!(err.to_string().contains("Header"))
741    }
742
743    #[test]
744    fn test_parse_body() {
745        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
746
747        let mut reader = MessageDecoder::<Request>::default();
748        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
749        let mut pl = pl.unwrap();
750        assert_eq!(req.version(), Version::HTTP_11);
751        assert_eq!(*req.method(), Method::GET);
752        assert_eq!(req.path(), "/test");
753        assert_eq!(
754            pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
755            b"body"
756        );
757    }
758
759    #[test]
760    fn test_parse_body_crlf() {
761        let mut buf = BytesMut::from("\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
762
763        let mut reader = MessageDecoder::<Request>::default();
764        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
765        let mut pl = pl.unwrap();
766        assert_eq!(req.version(), Version::HTTP_11);
767        assert_eq!(*req.method(), Method::GET);
768        assert_eq!(req.path(), "/test");
769        assert_eq!(
770            pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
771            b"body"
772        );
773    }
774
775    #[test]
776    fn test_parse_partial_eof() {
777        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n");
778        let mut reader = MessageDecoder::<Request>::default();
779        assert!(reader.decode(&mut buf).unwrap().is_none());
780
781        buf.extend(b"\r\n");
782        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
783        assert_eq!(req.version(), Version::HTTP_11);
784        assert_eq!(*req.method(), Method::GET);
785        assert_eq!(req.path(), "/test");
786    }
787
788    #[test]
789    fn test_headers_split_field() {
790        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n");
791
792        let mut reader = MessageDecoder::<Request>::default();
793        assert! { reader.decode(&mut buf).unwrap().is_none() }
794
795        buf.extend(b"t");
796        assert! { reader.decode(&mut buf).unwrap().is_none() }
797
798        buf.extend(b"es");
799        assert! { reader.decode(&mut buf).unwrap().is_none() }
800
801        buf.extend(b"t: value\r\n\r\n");
802        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
803        assert_eq!(req.version(), Version::HTTP_11);
804        assert_eq!(*req.method(), Method::GET);
805        assert_eq!(req.path(), "/test");
806        assert_eq!(
807            req.headers()
808                .get(HeaderName::try_from("test").unwrap())
809                .unwrap()
810                .as_bytes(),
811            b"value"
812        );
813    }
814
815    #[test]
816    fn test_headers_multi_value() {
817        let mut buf = BytesMut::from(
818            "GET /test HTTP/1.1\r\n\
819             Set-Cookie: c1=cookie1\r\n\
820             Set-Cookie: c2=cookie2\r\n\r\n",
821        );
822        let mut reader = MessageDecoder::<Request>::default();
823        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
824
825        let val: Vec<_> = req
826            .headers()
827            .get_all(SET_COOKIE)
828            .map(|v| v.to_str().unwrap().to_owned())
829            .collect();
830        assert_eq!(val[0], "c1=cookie1");
831        assert_eq!(val[1], "c2=cookie2");
832    }
833
834    #[test]
835    fn test_conn_default_1_0() {
836        let req = parse_ready!(&mut BytesMut::from("GET /test HTTP/1.0\r\n\r\n"));
837        assert_eq!(req.head().connection_type(), ConnectionType::Close);
838    }
839
840    #[test]
841    fn test_conn_default_1_1() {
842        let req = parse_ready!(&mut BytesMut::from("GET /test HTTP/1.1\r\n\r\n"));
843        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
844    }
845
846    #[test]
847    fn test_conn_close() {
848        let req = parse_ready!(&mut BytesMut::from(
849            "GET /test HTTP/1.1\r\n\
850             connection: close\r\n\r\n",
851        ));
852        assert_eq!(req.head().connection_type(), ConnectionType::Close);
853
854        let req = parse_ready!(&mut BytesMut::from(
855            "GET /test HTTP/1.1\r\n\
856             connection: Close\r\n\r\n",
857        ));
858        assert_eq!(req.head().connection_type(), ConnectionType::Close);
859    }
860
861    #[test]
862    fn test_conn_close_1_0() {
863        let req = parse_ready!(&mut BytesMut::from(
864            "GET /test HTTP/1.0\r\n\
865             connection: close\r\n\r\n",
866        ));
867        assert_eq!(req.head().connection_type(), ConnectionType::Close);
868    }
869
870    #[test]
871    fn test_conn_keep_alive_1_0() {
872        let req = parse_ready!(&mut BytesMut::from(
873            "GET /test HTTP/1.0\r\n\
874             connection: keep-alive\r\n\r\n",
875        ));
876        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
877
878        let req = parse_ready!(&mut BytesMut::from(
879            "GET /test HTTP/1.0\r\n\
880             connection: Keep-Alive\r\n\r\n",
881        ));
882        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
883    }
884
885    #[test]
886    fn test_conn_keep_alive_1_1() {
887        let req = parse_ready!(&mut BytesMut::from(
888            "GET /test HTTP/1.1\r\n\
889             connection: keep-alive\r\n\r\n",
890        ));
891        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
892    }
893
894    #[test]
895    fn test_conn_other_1_0() {
896        let req = parse_ready!(&mut BytesMut::from(
897            "GET /test HTTP/1.0\r\n\
898             connection: other\r\n\r\n",
899        ));
900        assert_eq!(req.head().connection_type(), ConnectionType::Close);
901    }
902
903    #[test]
904    fn test_conn_other_1_1() {
905        let req = parse_ready!(&mut BytesMut::from(
906            "GET /test HTTP/1.1\r\n\
907             connection: other\r\n\r\n",
908        ));
909        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
910    }
911
912    #[test]
913    fn test_conn_upgrade() {
914        let req = parse_ready!(&mut BytesMut::from(
915            "GET /test HTTP/1.1\r\n\
916             upgrade: websockets\r\n\
917             connection: upgrade\r\n\r\n",
918        ));
919
920        assert!(req.upgrade());
921        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
922
923        let req = parse_ready!(&mut BytesMut::from(
924            "GET /test HTTP/1.1\r\n\
925             upgrade: Websockets\r\n\
926             connection: Upgrade\r\n\r\n",
927        ));
928
929        assert!(req.upgrade());
930        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
931    }
932
933    #[test]
934    fn test_conn_upgrade_connect_method() {
935        let req = parse_ready!(&mut BytesMut::from(
936            "CONNECT /test HTTP/1.1\r\n\
937             content-type: text/plain\r\n\r\n",
938        ));
939
940        assert!(req.upgrade());
941    }
942
943    #[test]
944    fn test_headers_bad_content_length() {
945        // string CL
946        expect_parse_err!(&mut BytesMut::from(
947            "GET /test HTTP/1.1\r\n\
948             content-length: line\r\n\r\n",
949        ));
950
951        // negative CL
952        expect_parse_err!(&mut BytesMut::from(
953            "GET /test HTTP/1.1\r\n\
954             content-length: -1\r\n\r\n",
955        ));
956    }
957
958    #[test]
959    fn octal_ish_cl_parsed_as_decimal() {
960        let mut buf = BytesMut::from(
961            "POST /test HTTP/1.1\r\n\
962             content-length: 011\r\n\r\n",
963        );
964        let mut reader = MessageDecoder::<Request>::default();
965        let (_req, pl) = reader.decode(&mut buf).unwrap().unwrap();
966        assert!(matches!(
967            pl,
968            PayloadType::Payload(pl) if pl == PayloadDecoder::length(11)
969        ));
970    }
971
972    #[test]
973    fn test_invalid_header() {
974        expect_parse_err!(&mut BytesMut::from(
975            "GET /test HTTP/1.1\r\n\
976             test line\r\n\r\n",
977        ));
978    }
979
980    #[test]
981    fn test_invalid_name() {
982        expect_parse_err!(&mut BytesMut::from(
983            "GET /test HTTP/1.1\r\n\
984             test[]: line\r\n\r\n",
985        ));
986    }
987
988    #[test]
989    fn test_http_request_bad_status_line() {
990        expect_parse_err!(&mut BytesMut::from("getpath \r\n\r\n"));
991    }
992
993    #[test]
994    fn test_http_request_upgrade_websocket() {
995        let mut buf = BytesMut::from(
996            "GET /test HTTP/1.1\r\n\
997             connection: upgrade\r\n\
998             upgrade: websocket\r\n\r\n\
999             some raw data",
1000        );
1001        let mut reader = MessageDecoder::<Request>::default();
1002        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1003        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
1004        assert!(req.upgrade());
1005        assert!(pl.is_unhandled());
1006    }
1007
1008    #[test]
1009    fn test_http_request_upgrade_h2c() {
1010        let mut buf = BytesMut::from(
1011            "GET /test HTTP/1.1\r\n\
1012             connection: upgrade, http2-settings\r\n\
1013             upgrade: h2c\r\n\
1014             http2-settings: dummy\r\n\r\n",
1015        );
1016        let mut reader = MessageDecoder::<Request>::default();
1017        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1018        // `connection: upgrade, http2-settings` doesn't work properly..
1019        // see MessageType::set_headers().
1020        //
1021        // The line below should be:
1022        // assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
1023        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
1024        assert!(req.upgrade());
1025        assert!(!pl.is_unhandled());
1026    }
1027
1028    #[test]
1029    fn test_http_request_parser_utf8() {
1030        let req = parse_ready!(&mut BytesMut::from(
1031            "GET /test HTTP/1.1\r\n\
1032             x-test: тест\r\n\r\n",
1033        ));
1034
1035        assert_eq!(
1036            req.headers().get("x-test").unwrap().as_bytes(),
1037            "тест".as_bytes()
1038        );
1039    }
1040
1041    #[test]
1042    fn test_http_request_parser_two_slashes() {
1043        let req = parse_ready!(&mut BytesMut::from("GET //path HTTP/1.1\r\n\r\n"));
1044        assert_eq!(req.path(), "//path");
1045    }
1046
1047    #[test]
1048    fn test_http_request_parser_bad_method() {
1049        expect_parse_err!(&mut BytesMut::from("!12%()+=~$ /get HTTP/1.1\r\n\r\n"));
1050    }
1051
1052    #[test]
1053    fn test_http_request_parser_bad_version() {
1054        expect_parse_err!(&mut BytesMut::from("GET //get HT/11\r\n\r\n"));
1055    }
1056
1057    #[test]
1058    fn test_response_http10_read_until_eof() {
1059        let mut buf = BytesMut::from("HTTP/1.0 200 Ok\r\n\r\ntest data");
1060
1061        let mut reader = MessageDecoder::<ResponseHead>::default();
1062        let (_msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
1063        let mut pl = pl.unwrap();
1064
1065        let chunk = pl.decode(&mut buf).unwrap().unwrap();
1066        assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"test data")));
1067    }
1068
1069    #[test]
1070    fn hrs_multiple_content_length() {
1071        expect_parse_err!(&mut BytesMut::from(
1072            "GET / HTTP/1.1\r\n\
1073            Host: example.com\r\n\
1074            Content-Length: 4\r\n\
1075            Content-Length: 2\r\n\
1076            \r\n\
1077            abcd",
1078        ));
1079
1080        expect_parse_err!(&mut BytesMut::from(
1081            "GET / HTTP/1.1\r\n\
1082            Host: example.com\r\n\
1083            Content-Length: 0\r\n\
1084            Content-Length: 2\r\n\
1085            \r\n\
1086            ab",
1087        ));
1088    }
1089
1090    #[test]
1091    fn hrs_content_length_plus() {
1092        expect_parse_err!(&mut BytesMut::from(
1093            "GET / HTTP/1.1\r\n\
1094            Host: example.com\r\n\
1095            Content-Length: +3\r\n\
1096            \r\n\
1097            000",
1098        ));
1099    }
1100
1101    #[test]
1102    fn hrs_te_http10() {
1103        // in HTTP/1.0 transfer encoding is ignored and must therefore contain a CL header
1104
1105        expect_parse_err!(&mut BytesMut::from(
1106            "POST / HTTP/1.0\r\n\
1107            Host: example.com\r\n\
1108            Transfer-Encoding: chunked\r\n\
1109            \r\n\
1110            3\r\n\
1111            aaa\r\n\
1112            0\r\n\
1113            ",
1114        ));
1115    }
1116
1117    #[test]
1118    fn hrs_cl_and_te_http10() {
1119        // in HTTP/1.0 transfer encoding is simply ignored so it's fine to have both
1120
1121        let mut buf = BytesMut::from(
1122            "GET / HTTP/1.0\r\n\
1123            Host: example.com\r\n\
1124            Content-Length: 3\r\n\
1125            Transfer-Encoding: chunked\r\n\
1126            \r\n\
1127            000",
1128        );
1129
1130        parse_ready!(&mut buf);
1131    }
1132
1133    #[test]
1134    fn hrs_unknown_transfer_encoding() {
1135        let mut buf = BytesMut::from(
1136            "GET / HTTP/1.1\r\n\
1137            Host: example.com\r\n\
1138            Transfer-Encoding: JUNK\r\n\
1139            Transfer-Encoding: chunked\r\n\
1140            \r\n\
1141            5\r\n\
1142            hello\r\n\
1143            0",
1144        );
1145
1146        expect_parse_err!(&mut buf);
1147    }
1148
1149    #[test]
1150    fn hrs_multiple_transfer_encoding() {
1151        let mut buf = BytesMut::from(
1152            "GET / HTTP/1.1\r\n\
1153            Host: example.com\r\n\
1154            Content-Length: 51\r\n\
1155            Transfer-Encoding: identity\r\n\
1156            Transfer-Encoding: chunked\r\n\
1157            \r\n\
1158            0\r\n\
1159            \r\n\
1160            GET /forbidden HTTP/1.1\r\n\
1161            Host: example.com\r\n\r\n",
1162        );
1163
1164        expect_parse_err!(&mut buf);
1165    }
1166
1167    #[test]
1168    fn transfer_encoding_agrees() {
1169        let mut buf = BytesMut::from(
1170            "GET /test HTTP/1.1\r\n\
1171            Host: example.com\r\n\
1172            Content-Length: 3\r\n\
1173            Transfer-Encoding: identity\r\n\
1174            \r\n\
1175            0\r\n",
1176        );
1177
1178        let mut reader = MessageDecoder::<Request>::default();
1179        let (_msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
1180        let mut pl = pl.unwrap();
1181
1182        let chunk = pl.decode(&mut buf).unwrap().unwrap();
1183        assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"0\r\n")));
1184    }
1185}