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        if msg.head().headers.contains_key(header::TRANSFER_ENCODING) {
279            if ver == Version::HTTP_10 {
280                debug!("Transfer-Encoding is not allowed in HTTP/1.0 requests");
281                return Err(ParseError::Header);
282            }
283
284            if !crate::HttpMessage::chunked(&msg)? {
285                debug!("request Transfer-Encoding must be chunked");
286                return Err(ParseError::Header);
287            }
288
289            if msg.head().headers.contains_key(header::CONTENT_LENGTH) {
290                debug!("both Content-Length and Transfer-Encoding are set");
291                return Err(ParseError::Header);
292            }
293        }
294
295        // disallow HTTP/1.0 POST requests that do not contain a Content-Length headers
296        // see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2
297        if ver == Version::HTTP_10 && method == Method::POST && length.is_none() {
298            debug!("no Content-Length specified for HTTP/1.0 POST request");
299            return Err(ParseError::Header);
300        }
301
302        // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
303        // Protects against some request smuggling attacks.
304        // See https://github.com/actix/actix-web/issues/2767.
305        if length.is_zero() {
306            length = PayloadLength::None;
307        }
308
309        // payload decoder
310        let decoder = match length {
311            PayloadLength::Payload(pl) => pl,
312            PayloadLength::UpgradeWebSocket => {
313                // upgrade (WebSocket)
314                PayloadType::Stream(PayloadDecoder::eof())
315            }
316            PayloadLength::None => {
317                if method == Method::CONNECT {
318                    PayloadType::Stream(PayloadDecoder::eof())
319                } else {
320                    PayloadType::None
321                }
322            }
323        };
324
325        let head = msg.head_mut();
326        head.uri = uri;
327        head.method = method;
328        head.version = ver;
329
330        Ok(Some((msg, decoder)))
331    }
332}
333
334impl MessageType for ResponseHead {
335    fn set_connection_type(&mut self, conn_type: Option<ConnectionType>) {
336        if let Some(ctype) = conn_type {
337            ResponseHead::set_connection_type(self, ctype);
338        }
339    }
340
341    fn set_expect(&mut self) {}
342
343    fn headers_mut(&mut self) -> &mut HeaderMap {
344        &mut self.headers
345    }
346
347    fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError> {
348        let mut headers: [HeaderIndex; MAX_HEADERS] = EMPTY_HEADER_INDEX_ARRAY;
349
350        let (len, ver, status, h_len) = {
351            // SAFETY:
352            // Create an uninitialized array of `MaybeUninit`. The `assume_init` is safe because the
353            // type we are claiming to have initialized here is a bunch of `MaybeUninit`s, which
354            // do not require initialization.
355            let mut parsed = unsafe {
356                MaybeUninit::<[MaybeUninit<httparse::Header<'_>>; MAX_HEADERS]>::uninit()
357                    .assume_init()
358            };
359
360            let mut res = httparse::Response::new(&mut []);
361
362            let mut config = httparse::ParserConfig::default();
363            config.allow_spaces_after_header_name_in_responses(true);
364
365            match config.parse_response_with_uninit_headers(&mut res, src, &mut parsed)? {
366                httparse::Status::Complete(len) => {
367                    let version = if res.version.unwrap() == 1 {
368                        Version::HTTP_11
369                    } else {
370                        Version::HTTP_10
371                    };
372
373                    let status =
374                        StatusCode::from_u16(res.code.unwrap()).map_err(|_| ParseError::Status)?;
375                    HeaderIndex::record(src, res.headers, &mut headers);
376
377                    (len, version, status, res.headers.len())
378                }
379
380                httparse::Status::Partial => {
381                    return if src.len() >= MAX_BUFFER_SIZE {
382                        error!("MAX_BUFFER_SIZE unprocessed data reached, closing");
383                        Err(ParseError::TooLarge)
384                    } else {
385                        Ok(None)
386                    }
387                }
388            }
389        };
390
391        let mut msg = ResponseHead::new(status);
392        msg.version = ver;
393
394        // convert headers
395        let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?;
396
397        // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed.
398        // Protects against some request smuggling attacks.
399        // See https://github.com/actix/actix-web/issues/2767.
400        if length.is_zero() {
401            length = PayloadLength::None;
402        }
403
404        // message payload
405        let decoder = if let PayloadLength::Payload(pl) = length {
406            pl
407        } else if status == StatusCode::SWITCHING_PROTOCOLS {
408            // switching protocol or connect
409            PayloadType::Stream(PayloadDecoder::eof())
410        } else {
411            // for HTTP/1.0 read to eof and close connection
412            if msg.version == Version::HTTP_10 {
413                msg.set_connection_type(ConnectionType::Close);
414                PayloadType::Payload(PayloadDecoder::eof())
415            } else {
416                PayloadType::None
417            }
418        };
419
420        Ok(Some((msg, decoder)))
421    }
422}
423
424#[derive(Clone, Copy)]
425pub(crate) struct HeaderIndex {
426    pub(crate) name: (usize, usize),
427    pub(crate) value: (usize, usize),
428}
429
430pub(crate) const EMPTY_HEADER_INDEX: HeaderIndex = HeaderIndex {
431    name: (0, 0),
432    value: (0, 0),
433};
434
435pub(crate) const EMPTY_HEADER_INDEX_ARRAY: [HeaderIndex; MAX_HEADERS] =
436    [EMPTY_HEADER_INDEX; MAX_HEADERS];
437
438impl HeaderIndex {
439    pub(crate) fn record(
440        bytes: &[u8],
441        headers: &[httparse::Header<'_>],
442        indices: &mut [HeaderIndex],
443    ) {
444        let bytes_ptr = bytes.as_ptr() as usize;
445        for (header, indices) in headers.iter().zip(indices.iter_mut()) {
446            let name_start = header.name.as_ptr() as usize - bytes_ptr;
447            let name_end = name_start + header.name.len();
448            indices.name = (name_start, name_end);
449            let value_start = header.value.as_ptr() as usize - bytes_ptr;
450            let value_end = value_start + header.value.len();
451            indices.value = (value_start, value_end);
452        }
453    }
454}
455
456#[derive(Debug, Clone, PartialEq, Eq)]
457/// Chunk type yielded while decoding a payload.
458pub enum PayloadItem {
459    Chunk(Bytes),
460    Eof,
461}
462
463/// Decoder that can handle different payload types.
464///
465/// If a message body does not use `Transfer-Encoding`, it should include a `Content-Length`.
466#[derive(Debug, Clone, PartialEq, Eq)]
467pub struct PayloadDecoder {
468    kind: Kind,
469}
470
471impl PayloadDecoder {
472    /// Constructs a fixed-length payload decoder.
473    pub fn length(x: u64) -> PayloadDecoder {
474        PayloadDecoder {
475            kind: Kind::Length(x),
476        }
477    }
478
479    /// Constructs a chunked encoding decoder.
480    pub fn chunked() -> PayloadDecoder {
481        PayloadDecoder {
482            kind: Kind::Chunked(ChunkedState::Size, 0),
483        }
484    }
485
486    /// Creates an decoder that yields chunks until the stream returns EOF.
487    pub fn eof() -> PayloadDecoder {
488        PayloadDecoder { kind: Kind::Eof }
489    }
490}
491
492#[derive(Debug, Clone, PartialEq, Eq)]
493enum Kind {
494    /// A reader used when a `Content-Length` header is passed with a positive integer.
495    Length(u64),
496
497    /// A reader used when `Transfer-Encoding` is `chunked`.
498    Chunked(ChunkedState, u64),
499
500    /// A reader used for responses that don't indicate a length or chunked.
501    ///
502    /// Note: This should only used for `Response`s. It is illegal for a `Request` to be made
503    /// without either of `Content-Length` and `Transfer-Encoding: chunked` missing, as explained
504    /// in [RFC 7230 §3.3.3]:
505    ///
506    /// > If a Transfer-Encoding header field is present in a response and the chunked transfer
507    /// > coding is not the final encoding, the message body length is determined by reading the
508    /// > connection until it is closed by the server. If a Transfer-Encoding header field is
509    /// > present in a request and the chunked transfer coding is not the final encoding, the
510    /// > message body length cannot be determined reliably; the server MUST respond with the 400
511    /// > (Bad Request) status code and then close the connection.
512    ///
513    /// [RFC 7230 §3.3.3]: https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
514    Eof,
515}
516
517impl Decoder for PayloadDecoder {
518    type Item = PayloadItem;
519    type Error = io::Error;
520
521    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
522        match self.kind {
523            Kind::Length(ref mut remaining) => {
524                if *remaining == 0 {
525                    Ok(Some(PayloadItem::Eof))
526                } else {
527                    if src.is_empty() {
528                        return Ok(None);
529                    }
530                    let len = src.len() as u64;
531                    let buf;
532                    if *remaining > len {
533                        buf = src.split().freeze();
534                        *remaining -= len;
535                    } else {
536                        buf = src.split_to(*remaining as usize).freeze();
537                        *remaining = 0;
538                    };
539                    trace!("Length read: {}", buf.len());
540                    Ok(Some(PayloadItem::Chunk(buf)))
541                }
542            }
543
544            Kind::Chunked(ref mut state, ref mut size) => {
545                loop {
546                    let mut buf = None;
547
548                    // advances the chunked state
549                    *state = match state.step(src, size, &mut buf) {
550                        Poll::Pending => return Ok(None),
551                        Poll::Ready(Ok(state)) => state,
552                        Poll::Ready(Err(err)) => return Err(err),
553                    };
554
555                    if *state == ChunkedState::End {
556                        trace!("End of chunked stream");
557                        return Ok(Some(PayloadItem::Eof));
558                    }
559
560                    if let Some(buf) = buf {
561                        return Ok(Some(PayloadItem::Chunk(buf)));
562                    }
563
564                    if src.is_empty() {
565                        return Ok(None);
566                    }
567                }
568            }
569
570            Kind::Eof => {
571                if src.is_empty() {
572                    Ok(None)
573                } else {
574                    Ok(Some(PayloadItem::Chunk(src.split().freeze())))
575                }
576            }
577        }
578    }
579}
580
581#[cfg(test)]
582mod tests {
583    use super::*;
584    use crate::{header::SET_COOKIE, HttpMessage as _};
585
586    impl PayloadType {
587        pub(crate) fn unwrap(self) -> PayloadDecoder {
588            match self {
589                PayloadType::Payload(pl) => pl,
590                _ => panic!(),
591            }
592        }
593
594        pub(crate) fn is_unhandled(&self) -> bool {
595            matches!(self, PayloadType::Stream(_))
596        }
597    }
598
599    impl PayloadItem {
600        pub(crate) fn chunk(self) -> Bytes {
601            match self {
602                PayloadItem::Chunk(chunk) => chunk,
603                _ => panic!("error"),
604            }
605        }
606
607        pub(crate) fn eof(&self) -> bool {
608            matches!(*self, PayloadItem::Eof)
609        }
610    }
611
612    macro_rules! parse_ready {
613        ($e:expr) => {{
614            match MessageDecoder::<Request>::default().decode($e) {
615                Ok(Some((msg, _))) => msg,
616                Ok(_) => unreachable!("Eof during parsing http request"),
617                Err(err) => unreachable!("Error during parsing http request: {:?}", err),
618            }
619        }};
620    }
621
622    macro_rules! expect_parse_err {
623        ($e:expr) => {{
624            match MessageDecoder::<Request>::default().decode($e) {
625                Err(err) => match err {
626                    ParseError::Io(_) => unreachable!("Parse error expected"),
627                    _ => {}
628                },
629                _ => unreachable!("Error expected"),
630            }
631        }};
632    }
633
634    #[test]
635    fn test_parse() {
636        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n\r\n");
637
638        let mut reader = MessageDecoder::<Request>::default();
639        match reader.decode(&mut buf) {
640            Ok(Some((req, _))) => {
641                assert_eq!(req.version(), Version::HTTP_11);
642                assert_eq!(*req.method(), Method::GET);
643                assert_eq!(req.path(), "/test");
644            }
645            Ok(_) | Err(_) => unreachable!("Error during parsing http request"),
646        }
647    }
648
649    #[test]
650    fn test_parse_partial() {
651        let mut buf = BytesMut::from("PUT /test HTTP/1");
652
653        let mut reader = MessageDecoder::<Request>::default();
654        assert!(reader.decode(&mut buf).unwrap().is_none());
655
656        buf.extend(b".1\r\n\r\n");
657        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
658        assert_eq!(req.version(), Version::HTTP_11);
659        assert_eq!(*req.method(), Method::PUT);
660        assert_eq!(req.path(), "/test");
661    }
662
663    #[test]
664    fn parse_h09_reject() {
665        let mut buf = BytesMut::from(
666            "GET /test1 HTTP/0.9\r\n\
667            \r\n",
668        );
669
670        let mut reader = MessageDecoder::<Request>::default();
671        reader.decode(&mut buf).unwrap_err();
672
673        let mut buf = BytesMut::from(
674            "POST /test2 HTTP/0.9\r\n\
675            Content-Length: 3\r\n\
676            \r\n
677            abc",
678        );
679
680        let mut reader = MessageDecoder::<Request>::default();
681        reader.decode(&mut buf).unwrap_err();
682    }
683
684    #[test]
685    fn parse_h10_get() {
686        let mut buf = BytesMut::from(
687            "GET /test1 HTTP/1.0\r\n\
688            \r\n",
689        );
690
691        let mut reader = MessageDecoder::<Request>::default();
692        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
693        assert_eq!(req.version(), Version::HTTP_10);
694        assert_eq!(*req.method(), Method::GET);
695        assert_eq!(req.path(), "/test1");
696
697        let mut buf = BytesMut::from(
698            "GET /test2 HTTP/1.0\r\n\
699            Content-Length: 0\r\n\
700            \r\n",
701        );
702
703        let mut reader = MessageDecoder::<Request>::default();
704        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
705        assert_eq!(req.version(), Version::HTTP_10);
706        assert_eq!(*req.method(), Method::GET);
707        assert_eq!(req.path(), "/test2");
708
709        let mut buf = BytesMut::from(
710            "GET /test3 HTTP/1.0\r\n\
711            Content-Length: 3\r\n\
712            \r\n
713            abc",
714        );
715
716        let mut reader = MessageDecoder::<Request>::default();
717        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
718        assert_eq!(req.version(), Version::HTTP_10);
719        assert_eq!(*req.method(), Method::GET);
720        assert_eq!(req.path(), "/test3");
721    }
722
723    #[test]
724    fn parse_h10_post() {
725        let mut buf = BytesMut::from(
726            "POST /test1 HTTP/1.0\r\n\
727            Content-Length: 3\r\n\
728            \r\n\
729            abc",
730        );
731
732        let mut reader = MessageDecoder::<Request>::default();
733        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
734        assert_eq!(req.version(), Version::HTTP_10);
735        assert_eq!(*req.method(), Method::POST);
736        assert_eq!(req.path(), "/test1");
737
738        let mut buf = BytesMut::from(
739            "POST /test2 HTTP/1.0\r\n\
740            Content-Length: 0\r\n\
741            \r\n",
742        );
743
744        let mut reader = MessageDecoder::<Request>::default();
745        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
746        assert_eq!(req.version(), Version::HTTP_10);
747        assert_eq!(*req.method(), Method::POST);
748        assert_eq!(req.path(), "/test2");
749
750        let mut buf = BytesMut::from(
751            "POST /test3 HTTP/1.0\r\n\
752            \r\n",
753        );
754
755        let mut reader = MessageDecoder::<Request>::default();
756        let err = reader.decode(&mut buf).unwrap_err();
757        assert!(err.to_string().contains("Header"))
758    }
759
760    #[test]
761    fn test_parse_body() {
762        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
763
764        let mut reader = MessageDecoder::<Request>::default();
765        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
766        let mut pl = pl.unwrap();
767        assert_eq!(req.version(), Version::HTTP_11);
768        assert_eq!(*req.method(), Method::GET);
769        assert_eq!(req.path(), "/test");
770        assert_eq!(
771            pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
772            b"body"
773        );
774    }
775
776    #[test]
777    fn test_parse_body_crlf() {
778        let mut buf = BytesMut::from("\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody");
779
780        let mut reader = MessageDecoder::<Request>::default();
781        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
782        let mut pl = pl.unwrap();
783        assert_eq!(req.version(), Version::HTTP_11);
784        assert_eq!(*req.method(), Method::GET);
785        assert_eq!(req.path(), "/test");
786        assert_eq!(
787            pl.decode(&mut buf).unwrap().unwrap().chunk().as_ref(),
788            b"body"
789        );
790    }
791
792    #[test]
793    fn test_parse_partial_eof() {
794        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n");
795        let mut reader = MessageDecoder::<Request>::default();
796        assert!(reader.decode(&mut buf).unwrap().is_none());
797
798        buf.extend(b"\r\n");
799        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
800        assert_eq!(req.version(), Version::HTTP_11);
801        assert_eq!(*req.method(), Method::GET);
802        assert_eq!(req.path(), "/test");
803    }
804
805    #[test]
806    fn test_headers_split_field() {
807        let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n");
808
809        let mut reader = MessageDecoder::<Request>::default();
810        assert! { reader.decode(&mut buf).unwrap().is_none() }
811
812        buf.extend(b"t");
813        assert! { reader.decode(&mut buf).unwrap().is_none() }
814
815        buf.extend(b"es");
816        assert! { reader.decode(&mut buf).unwrap().is_none() }
817
818        buf.extend(b"t: value\r\n\r\n");
819        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
820        assert_eq!(req.version(), Version::HTTP_11);
821        assert_eq!(*req.method(), Method::GET);
822        assert_eq!(req.path(), "/test");
823        assert_eq!(
824            req.headers()
825                .get(HeaderName::try_from("test").unwrap())
826                .unwrap()
827                .as_bytes(),
828            b"value"
829        );
830    }
831
832    #[test]
833    fn test_headers_multi_value() {
834        let mut buf = BytesMut::from(
835            "GET /test HTTP/1.1\r\n\
836             Set-Cookie: c1=cookie1\r\n\
837             Set-Cookie: c2=cookie2\r\n\r\n",
838        );
839        let mut reader = MessageDecoder::<Request>::default();
840        let (req, _) = reader.decode(&mut buf).unwrap().unwrap();
841
842        let val: Vec<_> = req
843            .headers()
844            .get_all(SET_COOKIE)
845            .map(|v| v.to_str().unwrap().to_owned())
846            .collect();
847        assert_eq!(val[0], "c1=cookie1");
848        assert_eq!(val[1], "c2=cookie2");
849    }
850
851    #[test]
852    fn test_conn_default_1_0() {
853        let req = parse_ready!(&mut BytesMut::from("GET /test HTTP/1.0\r\n\r\n"));
854        assert_eq!(req.head().connection_type(), ConnectionType::Close);
855    }
856
857    #[test]
858    fn test_conn_default_1_1() {
859        let req = parse_ready!(&mut BytesMut::from("GET /test HTTP/1.1\r\n\r\n"));
860        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
861    }
862
863    #[test]
864    fn test_conn_close() {
865        let req = parse_ready!(&mut BytesMut::from(
866            "GET /test HTTP/1.1\r\n\
867             connection: close\r\n\r\n",
868        ));
869        assert_eq!(req.head().connection_type(), ConnectionType::Close);
870
871        let req = parse_ready!(&mut BytesMut::from(
872            "GET /test HTTP/1.1\r\n\
873             connection: Close\r\n\r\n",
874        ));
875        assert_eq!(req.head().connection_type(), ConnectionType::Close);
876    }
877
878    #[test]
879    fn test_conn_close_1_0() {
880        let req = parse_ready!(&mut BytesMut::from(
881            "GET /test HTTP/1.0\r\n\
882             connection: close\r\n\r\n",
883        ));
884        assert_eq!(req.head().connection_type(), ConnectionType::Close);
885    }
886
887    #[test]
888    fn test_conn_keep_alive_1_0() {
889        let req = parse_ready!(&mut BytesMut::from(
890            "GET /test HTTP/1.0\r\n\
891             connection: keep-alive\r\n\r\n",
892        ));
893        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
894
895        let req = parse_ready!(&mut BytesMut::from(
896            "GET /test HTTP/1.0\r\n\
897             connection: Keep-Alive\r\n\r\n",
898        ));
899        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
900    }
901
902    #[test]
903    fn test_conn_keep_alive_1_1() {
904        let req = parse_ready!(&mut BytesMut::from(
905            "GET /test HTTP/1.1\r\n\
906             connection: keep-alive\r\n\r\n",
907        ));
908        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
909    }
910
911    #[test]
912    fn test_conn_other_1_0() {
913        let req = parse_ready!(&mut BytesMut::from(
914            "GET /test HTTP/1.0\r\n\
915             connection: other\r\n\r\n",
916        ));
917        assert_eq!(req.head().connection_type(), ConnectionType::Close);
918    }
919
920    #[test]
921    fn test_conn_other_1_1() {
922        let req = parse_ready!(&mut BytesMut::from(
923            "GET /test HTTP/1.1\r\n\
924             connection: other\r\n\r\n",
925        ));
926        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
927    }
928
929    #[test]
930    fn test_conn_upgrade() {
931        let req = parse_ready!(&mut BytesMut::from(
932            "GET /test HTTP/1.1\r\n\
933             upgrade: websockets\r\n\
934             connection: upgrade\r\n\r\n",
935        ));
936
937        assert!(req.upgrade());
938        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
939
940        let req = parse_ready!(&mut BytesMut::from(
941            "GET /test HTTP/1.1\r\n\
942             upgrade: Websockets\r\n\
943             connection: Upgrade\r\n\r\n",
944        ));
945
946        assert!(req.upgrade());
947        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
948    }
949
950    #[test]
951    fn test_conn_upgrade_connect_method() {
952        let req = parse_ready!(&mut BytesMut::from(
953            "CONNECT /test HTTP/1.1\r\n\
954             content-type: text/plain\r\n\r\n",
955        ));
956
957        assert!(req.upgrade());
958    }
959
960    #[test]
961    fn test_headers_bad_content_length() {
962        // string CL
963        expect_parse_err!(&mut BytesMut::from(
964            "GET /test HTTP/1.1\r\n\
965             content-length: line\r\n\r\n",
966        ));
967
968        // negative CL
969        expect_parse_err!(&mut BytesMut::from(
970            "GET /test HTTP/1.1\r\n\
971             content-length: -1\r\n\r\n",
972        ));
973    }
974
975    #[test]
976    fn octal_ish_cl_parsed_as_decimal() {
977        let mut buf = BytesMut::from(
978            "POST /test HTTP/1.1\r\n\
979             content-length: 011\r\n\r\n",
980        );
981        let mut reader = MessageDecoder::<Request>::default();
982        let (_req, pl) = reader.decode(&mut buf).unwrap().unwrap();
983        assert!(matches!(
984            pl,
985            PayloadType::Payload(pl) if pl == PayloadDecoder::length(11)
986        ));
987    }
988
989    #[test]
990    fn test_invalid_header() {
991        expect_parse_err!(&mut BytesMut::from(
992            "GET /test HTTP/1.1\r\n\
993             test line\r\n\r\n",
994        ));
995    }
996
997    #[test]
998    fn test_invalid_name() {
999        expect_parse_err!(&mut BytesMut::from(
1000            "GET /test HTTP/1.1\r\n\
1001             test[]: line\r\n\r\n",
1002        ));
1003    }
1004
1005    #[test]
1006    fn test_http_request_bad_status_line() {
1007        expect_parse_err!(&mut BytesMut::from("getpath \r\n\r\n"));
1008    }
1009
1010    #[test]
1011    fn test_http_request_upgrade_websocket() {
1012        let mut buf = BytesMut::from(
1013            "GET /test HTTP/1.1\r\n\
1014             connection: upgrade\r\n\
1015             upgrade: websocket\r\n\r\n\
1016             some raw data",
1017        );
1018        let mut reader = MessageDecoder::<Request>::default();
1019        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1020        assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
1021        assert!(req.upgrade());
1022        assert!(pl.is_unhandled());
1023    }
1024
1025    #[test]
1026    fn test_http_request_upgrade_h2c() {
1027        let mut buf = BytesMut::from(
1028            "GET /test HTTP/1.1\r\n\
1029             connection: upgrade, http2-settings\r\n\
1030             upgrade: h2c\r\n\
1031             http2-settings: dummy\r\n\r\n",
1032        );
1033        let mut reader = MessageDecoder::<Request>::default();
1034        let (req, pl) = reader.decode(&mut buf).unwrap().unwrap();
1035        // `connection: upgrade, http2-settings` doesn't work properly..
1036        // see MessageType::set_headers().
1037        //
1038        // The line below should be:
1039        // assert_eq!(req.head().connection_type(), ConnectionType::Upgrade);
1040        assert_eq!(req.head().connection_type(), ConnectionType::KeepAlive);
1041        assert!(req.upgrade());
1042        assert!(!pl.is_unhandled());
1043    }
1044
1045    #[test]
1046    fn test_http_request_parser_utf8() {
1047        let req = parse_ready!(&mut BytesMut::from(
1048            "GET /test HTTP/1.1\r\n\
1049             x-test: тест\r\n\r\n",
1050        ));
1051
1052        assert_eq!(
1053            req.headers().get("x-test").unwrap().as_bytes(),
1054            "тест".as_bytes()
1055        );
1056    }
1057
1058    #[test]
1059    fn test_http_request_parser_two_slashes() {
1060        let req = parse_ready!(&mut BytesMut::from("GET //path HTTP/1.1\r\n\r\n"));
1061        assert_eq!(req.path(), "//path");
1062    }
1063
1064    #[test]
1065    fn test_http_request_parser_bad_method() {
1066        expect_parse_err!(&mut BytesMut::from("!12%()+=~$ /get HTTP/1.1\r\n\r\n"));
1067    }
1068
1069    #[test]
1070    fn test_http_request_parser_bad_version() {
1071        expect_parse_err!(&mut BytesMut::from("GET //get HT/11\r\n\r\n"));
1072    }
1073
1074    #[test]
1075    fn test_response_http10_read_until_eof() {
1076        let mut buf = BytesMut::from("HTTP/1.0 200 Ok\r\n\r\ntest data");
1077
1078        let mut reader = MessageDecoder::<ResponseHead>::default();
1079        let (_msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
1080        let mut pl = pl.unwrap();
1081
1082        let chunk = pl.decode(&mut buf).unwrap().unwrap();
1083        assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"test data")));
1084    }
1085
1086    #[test]
1087    fn hrs_multiple_content_length() {
1088        expect_parse_err!(&mut BytesMut::from(
1089            "GET / HTTP/1.1\r\n\
1090            Host: example.com\r\n\
1091            Content-Length: 4\r\n\
1092            Content-Length: 2\r\n\
1093            \r\n\
1094            abcd",
1095        ));
1096
1097        expect_parse_err!(&mut BytesMut::from(
1098            "GET / HTTP/1.1\r\n\
1099            Host: example.com\r\n\
1100            Content-Length: 0\r\n\
1101            Content-Length: 2\r\n\
1102            \r\n\
1103            ab",
1104        ));
1105    }
1106
1107    #[test]
1108    fn hrs_content_length_plus() {
1109        expect_parse_err!(&mut BytesMut::from(
1110            "GET / HTTP/1.1\r\n\
1111            Host: example.com\r\n\
1112            Content-Length: +3\r\n\
1113            \r\n\
1114            000",
1115        ));
1116    }
1117
1118    #[test]
1119    fn hrs_te_http10() {
1120        // in HTTP/1.0 transfer encoding is ignored and must therefore contain a CL header
1121
1122        expect_parse_err!(&mut BytesMut::from(
1123            "POST / HTTP/1.0\r\n\
1124            Host: example.com\r\n\
1125            Transfer-Encoding: chunked\r\n\
1126            \r\n\
1127            3\r\n\
1128            aaa\r\n\
1129            0\r\n\
1130            ",
1131        ));
1132    }
1133
1134    #[test]
1135    fn hrs_cl_and_te_http10() {
1136        expect_parse_err!(&mut BytesMut::from(
1137            "GET / HTTP/1.0\r\n\
1138            Host: example.com\r\n\
1139            Content-Length: 3\r\n\
1140            Transfer-Encoding: chunked\r\n\
1141            \r\n\
1142            000",
1143        ));
1144    }
1145
1146    #[test]
1147    fn hrs_cl_and_chunked_te_http11() {
1148        expect_parse_err!(&mut BytesMut::from(
1149            "POST / HTTP/1.1\r\n\
1150            Host: example.com\r\n\
1151            Content-Length: 3\r\n\
1152            Transfer-Encoding: chunked\r\n\
1153            \r\n\
1154            0\r\n\
1155            \r\n",
1156        ));
1157
1158        expect_parse_err!(&mut BytesMut::from(
1159            "POST / HTTP/1.1\r\n\
1160            Host: example.com\r\n\
1161            Transfer-Encoding: chunked\r\n\
1162            Content-Length: 3\r\n\
1163            \r\n\
1164            0\r\n\
1165            \r\n",
1166        ));
1167    }
1168
1169    #[test]
1170    fn hrs_identity_te_http11() {
1171        expect_parse_err!(&mut BytesMut::from(
1172            "POST / HTTP/1.1\r\n\
1173            Host: example.com\r\n\
1174            Transfer-Encoding: identity\r\n\
1175            \r\n\
1176            0\r\n",
1177        ));
1178
1179        expect_parse_err!(&mut BytesMut::from(
1180            "POST / HTTP/1.1\r\n\
1181            Host: example.com\r\n\
1182            Content-Length: 3\r\n\
1183            Transfer-Encoding: identity\r\n\
1184            \r\n\
1185            0\r\n",
1186        ));
1187    }
1188
1189    #[test]
1190    fn hrs_unknown_transfer_encoding() {
1191        let mut buf = BytesMut::from(
1192            "GET / HTTP/1.1\r\n\
1193            Host: example.com\r\n\
1194            Transfer-Encoding: JUNK\r\n\
1195            Transfer-Encoding: chunked\r\n\
1196            \r\n\
1197            5\r\n\
1198            hello\r\n\
1199            0",
1200        );
1201
1202        expect_parse_err!(&mut buf);
1203    }
1204
1205    #[test]
1206    fn hrs_multiple_transfer_encoding() {
1207        let mut buf = BytesMut::from(
1208            "GET / HTTP/1.1\r\n\
1209            Host: example.com\r\n\
1210            Content-Length: 51\r\n\
1211            Transfer-Encoding: identity\r\n\
1212            Transfer-Encoding: chunked\r\n\
1213            \r\n\
1214            0\r\n\
1215            \r\n\
1216            GET /forbidden HTTP/1.1\r\n\
1217            Host: example.com\r\n\r\n",
1218        );
1219
1220        expect_parse_err!(&mut buf);
1221    }
1222
1223    #[test]
1224    fn hrs_chunked_te_http11() {
1225        let mut buf = BytesMut::from(
1226            "GET /test HTTP/1.1\r\n\
1227            Host: example.com\r\n\
1228            Transfer-Encoding: chunked\r\n\
1229            \r\n\
1230            1\r\n\
1231            a\r\n\
1232            0\r\n\
1233            \r\n",
1234        );
1235
1236        let mut reader = MessageDecoder::<Request>::default();
1237        let (_msg, pl) = reader.decode(&mut buf).unwrap().unwrap();
1238        let mut pl = pl.unwrap();
1239
1240        let chunk = pl.decode(&mut buf).unwrap().unwrap();
1241        assert_eq!(chunk, PayloadItem::Chunk(Bytes::from_static(b"a")));
1242    }
1243}