Skip to main content

ntex_httparse/
lib.rs

1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2#![deny(clippy::missing_safety_doc, clippy::undocumented_unsafe_blocks)]
3#![cfg_attr(test, deny(warnings))]
4
5//! # httparse
6//!
7//! A push library for parsing HTTP/1.x requests and responses.
8//!
9//! The focus is on speed and safety. Unsafe code is used to keep parsing fast,
10//! but unsafety is contained in a submodule, with invariants enforced. The
11//! parsing internals use an `Iterator` instead of direct indexing, while
12//! skipping bounds checks.
13//!
14//! SIMD optimizations are enabled automatically when available.
15//! If building an executable to be run on multiple platforms, and thus
16//! not passing `target_feature` or `target_cpu` flags to the compiler,
17//! runtime detection can still detect SSE4.2 or AVX2 support to provide
18//! massive wins.
19//!
20//! If compiling for a specific target, remembering to include
21//! `-C target_cpu=native` allows the detection to become compile time checks,
22//! making it *even* faster.
23
24use core::{fmt, result, str};
25
26use crate::iter::Bytes;
27
28mod iter;
29#[macro_use]
30mod macros;
31mod simd;
32
33/// Determines if byte is a method token char.
34///
35/// > ```notrust
36/// > token          = 1*tchar
37/// >
38/// > tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
39/// >                / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
40/// >                / DIGIT / ALPHA
41/// >                ; any VCHAR, except delimiters
42/// > ```
43#[inline]
44fn is_method_token(b: u8) -> bool {
45    match b {
46        // For the majority case, this can be faster than the table lookup.
47        b'A'..=b'Z' => true,
48        _ => TOKEN_MAP[b as usize],
49    }
50}
51
52// char codes to accept URI string.
53// i.e. b'!' <= char and char != 127
54// TODO: Make a stricter checking for URI string?
55static URI_MAP: [bool; 256] = byte_map!(
56    b'!'..=0x7e | 0x80..=0xFF
57);
58
59#[inline]
60pub(crate) fn is_uri_token(b: u8) -> bool {
61    URI_MAP[b as usize]
62}
63
64static TOKEN_MAP: [bool; 256] = byte_map!(
65    b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' |
66    b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' |  b'*' | b'+' |
67    b'-' | b'.' | b'^' | b'_' | b'`' | b'|' | b'~'
68);
69
70#[inline]
71pub(crate) fn is_header_name_token(b: u8) -> bool {
72    TOKEN_MAP[b as usize]
73}
74
75static HEADER_VALUE_MAP: [bool; 256] = byte_map!(
76    b'\t' | b' '..=0x7e | 0x80..=0xFF
77);
78
79#[inline]
80pub(crate) fn is_header_value_token(b: u8) -> bool {
81    HEADER_VALUE_MAP[b as usize]
82}
83
84/// An error in parsing.
85#[derive(Copy, Clone, PartialEq, Eq, Debug)]
86pub enum Error {
87    /// Invalid byte in header name.
88    HeaderName,
89    /// Invalid byte in header value.
90    HeaderValue,
91    /// Invalid byte in new line.
92    NewLine,
93    /// Invalid byte in Response status.
94    Status,
95    /// Invalid byte where token is required.
96    Token,
97    /// Parsed more headers than provided buffer can contain.
98    TooManyHeaders,
99    /// Invalid byte in HTTP version.
100    Version,
101}
102
103impl Error {
104    #[inline]
105    fn description_str(&self) -> &'static str {
106        match *self {
107            Error::HeaderName => "invalid header name",
108            Error::HeaderValue => "invalid header value",
109            Error::NewLine => "invalid new line",
110            Error::Status => "invalid response status",
111            Error::Token => "invalid token",
112            Error::TooManyHeaders => "too many headers",
113            Error::Version => "invalid HTTP version",
114        }
115    }
116}
117
118impl fmt::Display for Error {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        f.write_str(self.description_str())
121    }
122}
123
124#[cfg(feature = "std")]
125impl std::error::Error for Error {
126    fn description(&self) -> &str {
127        self.description_str()
128    }
129}
130
131/// An error in parsing a chunk size.
132// Note: Move this into the error enum once v2.0 is released.
133#[derive(Debug, PartialEq, Eq)]
134pub struct InvalidChunkSize;
135
136impl fmt::Display for InvalidChunkSize {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        f.write_str("invalid chunk size")
139    }
140}
141
142/// A Result of any parsing action.
143///
144/// If the input is invalid, an `Error` will be returned. Note that incomplete
145/// data is not considered invalid, and so will not return an error, but rather
146/// a `Ok(Status::Partial)`.
147pub type Result<T> = result::Result<Status<T>, Error>;
148
149/// The result of a successful parse pass.
150///
151/// `Complete` is used when the buffer contained the complete value.
152/// `Partial` is used when parsing did not reach the end of the expected value,
153/// but no invalid data was found.
154#[derive(Copy, Clone, Eq, PartialEq, Debug)]
155pub enum Status<T> {
156    /// The completed result.
157    Complete(T),
158    /// A partial result.
159    Partial,
160}
161
162impl<T> Status<T> {
163    /// Convenience method to check if status is complete.
164    #[inline]
165    pub fn is_complete(&self) -> bool {
166        match *self {
167            Status::Complete(..) => true,
168            Status::Partial => false,
169        }
170    }
171
172    /// Convenience method to check if status is partial.
173    #[inline]
174    pub fn is_partial(&self) -> bool {
175        match *self {
176            Status::Complete(..) => false,
177            Status::Partial => true,
178        }
179    }
180
181    /// Convenience method to unwrap a Complete value. Panics if the status is
182    /// `Partial`.
183    #[inline]
184    pub fn unwrap(self) -> T {
185        match self {
186            Status::Complete(t) => t,
187            Status::Partial => panic!("Tried to unwrap Status::Partial"),
188        }
189    }
190}
191
192/// Parser configuration.
193#[derive(Clone, Debug, Default)]
194pub struct ParserConfig {
195    allow_spaces_after_header_name_in_responses: bool,
196    allow_obsolete_multiline_headers_in_responses: bool,
197    allow_multiple_spaces_in_request_line_delimiters: bool,
198    allow_multiple_spaces_in_response_status_delimiters: bool,
199    allow_space_before_first_header_name: bool,
200    ignore_invalid_headers_in_responses: bool,
201    ignore_invalid_headers_in_requests: bool,
202}
203
204impl ParserConfig {
205    /// Sets whether spaces and tabs should be allowed after header names in responses.
206    pub fn allow_spaces_after_header_name_in_responses(&mut self, value: bool) -> &mut Self {
207        self.allow_spaces_after_header_name_in_responses = value;
208        self
209    }
210
211    /// Sets whether multiple spaces are allowed as delimiters in request lines.
212    ///
213    /// # Background
214    ///
215    /// The [latest version of the HTTP/1.1 spec][spec] allows implementations to parse multiple
216    /// whitespace characters in place of the `SP` delimiters in the request line, including:
217    ///
218    /// > SP, HTAB, VT (%x0B), FF (%x0C), or bare CR
219    ///
220    /// This option relaxes the parser to allow for multiple spaces, but does *not* allow the
221    /// request line to contain the other mentioned whitespace characters.
222    ///
223    /// [spec]: https://httpwg.org/http-core/draft-ietf-httpbis-messaging-latest.html#rfc.section.3.p.3
224    pub fn allow_multiple_spaces_in_request_line_delimiters(&mut self, value: bool) -> &mut Self {
225        self.allow_multiple_spaces_in_request_line_delimiters = value;
226        self
227    }
228
229    /// Whether multiple spaces are allowed as delimiters in request lines.
230    pub fn multiple_spaces_in_request_line_delimiters_are_allowed(&self) -> bool {
231        self.allow_multiple_spaces_in_request_line_delimiters
232    }
233
234    /// Sets whether multiple spaces are allowed as delimiters in response status lines.
235    ///
236    /// # Background
237    ///
238    /// The [latest version of the HTTP/1.1 spec][spec] allows implementations to parse multiple
239    /// whitespace characters in place of the `SP` delimiters in the response status line,
240    /// including:
241    ///
242    /// > SP, HTAB, VT (%x0B), FF (%x0C), or bare CR
243    ///
244    /// This option relaxes the parser to allow for multiple spaces, but does *not* allow the status
245    /// line to contain the other mentioned whitespace characters.
246    ///
247    /// [spec]: https://httpwg.org/http-core/draft-ietf-httpbis-messaging-latest.html#rfc.section.4.p.3
248    pub fn allow_multiple_spaces_in_response_status_delimiters(
249        &mut self,
250        value: bool,
251    ) -> &mut Self {
252        self.allow_multiple_spaces_in_response_status_delimiters = value;
253        self
254    }
255
256    /// Whether multiple spaces are allowed as delimiters in response status lines.
257    pub fn multiple_spaces_in_response_status_delimiters_are_allowed(&self) -> bool {
258        self.allow_multiple_spaces_in_response_status_delimiters
259    }
260
261    /// Sets whether obsolete multiline headers should be allowed.
262    ///
263    /// This is an obsolete part of HTTP/1. Use at your own risk. If you are
264    /// building an HTTP library, the newlines (`\r` and `\n`) should be
265    /// replaced by spaces before handing the header value to the user.
266    ///
267    /// # Example
268    ///
269    /// ```rust
270    /// let buf = b"HTTP/1.1 200 OK\r\nFolded-Header: hello\r\n there \r\n\r\n";
271    /// let mut headers = [httparse::EMPTY_HEADER; 16];
272    /// let mut response = httparse::Response::new(&mut headers);
273    ///
274    /// let res = httparse::ParserConfig::default()
275    ///     .allow_obsolete_multiline_headers_in_responses(true)
276    ///     .parse_response(&mut response, buf);
277    ///
278    /// assert_eq!(res, Ok(httparse::Status::Complete(buf.len())));
279    ///
280    /// assert_eq!(response.headers.len(), 1);
281    /// assert_eq!(response.headers[0].0, "Folded-Header");
282    /// assert_eq!(response.headers[0].1, b"hello\r\n there");
283    /// ```
284    pub fn allow_obsolete_multiline_headers_in_responses(&mut self, value: bool) -> &mut Self {
285        self.allow_obsolete_multiline_headers_in_responses = value;
286        self
287    }
288
289    /// Whether obsolete multiline headers should be allowed.
290    pub fn obsolete_multiline_headers_in_responses_are_allowed(&self) -> bool {
291        self.allow_obsolete_multiline_headers_in_responses
292    }
293
294    /// Sets whether white space before the first header is allowed
295    ///
296    /// This is not allowed by spec but some browsers ignore it. So this an option for
297    /// compatibility.
298    /// See https://github.com/curl/curl/issues/11605 for reference
299    /// # Example
300    ///
301    /// ```rust
302    /// let buf = b"HTTP/1.1 200 OK\r\n Space-Before-Header: hello there\r\n\r\n";
303    /// let mut headers = [httparse::EMPTY_HEADER; 1];
304    /// let mut response = httparse::Response::new(&mut headers[..]);
305    /// let result = httparse::ParserConfig::default()
306    ///     .allow_space_before_first_header_name(true)
307    ///     .parse_response(&mut response, buf);
308    ///
309    /// assert_eq!(result, Ok(httparse::Status::Complete(buf.len())));
310    /// assert_eq!(response.version.unwrap(), 1);
311    /// assert_eq!(response.code.unwrap(), 200);
312    /// assert_eq!(response.reason.unwrap(), "OK");
313    /// assert_eq!(response.headers.len(), 1);
314    /// assert_eq!(response.headers[0].0, "Space-Before-Header");
315    /// assert_eq!(response.headers[0].1, &b"hello there"[..]);
316    /// ```
317    pub fn allow_space_before_first_header_name(&mut self, value: bool) -> &mut Self {
318        self.allow_space_before_first_header_name = value;
319        self
320    }
321
322    /// Whether white space before first header is allowed or not
323    pub fn space_before_first_header_name_are_allowed(&self) -> bool {
324        self.allow_space_before_first_header_name
325    }
326
327    /// Sets whether invalid header lines should be silently ignored in responses.
328    ///
329    /// This mimicks the behaviour of major browsers. You probably don't want this.
330    /// You should only want this if you are implementing a proxy whose main
331    /// purpose is to sit in front of browsers whose users access arbitrary content
332    /// which may be malformed, and they expect everything that works without
333    /// the proxy to keep working with the proxy.
334    ///
335    /// This option will prevent `ParserConfig::parse_response` from returning
336    /// an error encountered when parsing a header, except if the error was caused
337    /// by the character NUL (ASCII code 0), as Chrome specifically always reject
338    /// those, or if the error was caused by a lone character `\r`, as Firefox and
339    /// Chrome behave differently in that case.
340    ///
341    /// The ignorable errors are:
342    /// * empty header names;
343    /// * characters that are not allowed in header names, except for `\0` and `\r`;
344    /// * when `allow_spaces_after_header_name_in_responses` is not enabled,
345    ///   spaces and tabs between the header name and the colon;
346    /// * missing colon between header name and value;
347    /// * when `allow_obsolete_multiline_headers_in_responses` is not enabled,
348    ///   headers using obsolete line folding.
349    /// * characters that are not allowed in header values except for `\0` and `\r`.
350    ///
351    /// If an ignorable error is encountered, the parser tries to find the next
352    /// line in the input to resume parsing the rest of the headers. As lines
353    /// contributing to a header using obsolete line folding always start
354    /// with whitespace, those will be ignored too. An error will be emitted
355    /// nonetheless if it finds `\0` or a lone `\r` while looking for the
356    /// next line.
357    pub fn ignore_invalid_headers_in_responses(&mut self, value: bool) -> &mut Self {
358        self.ignore_invalid_headers_in_responses = value;
359        self
360    }
361
362    /// Sets whether invalid header lines should be silently ignored in requests.
363    pub fn ignore_invalid_headers_in_requests(&mut self, value: bool) -> &mut Self {
364        self.ignore_invalid_headers_in_requests = value;
365        self
366    }
367}
368
369#[inline]
370fn skip_empty_lines(bytes: &mut Bytes<'_>) -> Result<()> {
371    loop {
372        let b = bytes.peek();
373        match b {
374            Some(b'\r') => {
375                // SAFETY: peeked and found `\r`, so it's safe to bump 1 pos
376                unsafe { bytes.bump() };
377                expect!(bytes.next() == b'\n' => Err(Error::NewLine));
378            }
379            Some(b'\n') => {
380                // SAFETY: peeked and found `\n`, so it's safe to bump 1 pos
381                unsafe {
382                    bytes.bump();
383                }
384            }
385            Some(..) => {
386                bytes.slice();
387                return Ok(Status::Complete(()));
388            }
389            None => return Ok(Status::Partial),
390        }
391    }
392}
393
394#[inline]
395fn skip_spaces(bytes: &mut Bytes<'_>) -> Result<()> {
396    loop {
397        let b = bytes.peek();
398        match b {
399            Some(b' ') => {
400                // SAFETY: peeked and found ` `, so it's safe to bump 1 pos
401                unsafe { bytes.bump() };
402            }
403            Some(..) => {
404                bytes.slice();
405                return Ok(Status::Complete(()));
406            }
407            None => return Ok(Status::Partial),
408        }
409    }
410}
411
412#[inline]
413/// Parse response code and reason
414pub fn parse_request<'b>(src: &'b [u8]) -> Result<(usize, &'b str, &'b str, u8)> {
415    let mut bytes = Bytes::new(src);
416
417    let method = complete!(parse_method(&mut bytes));
418    let path = complete!(parse_uri(&mut bytes));
419    let version = complete!(parse_version(&mut bytes));
420    newline!(bytes);
421    Ok(Status::Complete((bytes.slice_pos(), method, path, version)))
422}
423
424#[inline]
425/// Parse response code and reason
426pub fn parse_response<'b>(buf: &'b [u8]) -> Result<(usize, u8, u16, &'b str)> {
427    let mut bytes = Bytes::new(buf);
428
429    complete!(skip_empty_lines(&mut bytes));
430    let version = complete!(parse_version(&mut bytes));
431    complete!(skip_empty_lines(&mut bytes));
432    space!(bytes or Error::Version);
433    complete!(skip_spaces(&mut bytes));
434    let code = complete!(parse_code(&mut bytes));
435
436    // RFC7230 says there must be 'SP' and then reason-phrase, but admits
437    // its only for legacy reasons. With the reason-phrase completely
438    // optional (and preferred to be omitted) in HTTP2, we'll just
439    // handle any response that doesn't include a reason-phrase, because
440    // it's more lenient, and we don't care anyways.
441    //
442    // So, a SP means parse a reason-phrase.
443    // A newline means go to headers.
444    // Anything else we'll say is a malformed status.
445    let reason = match next!(bytes) {
446        b' ' => {
447            complete!(skip_spaces(&mut bytes));
448            bytes.slice();
449            complete!(parse_reason(&mut bytes))
450        }
451        b'\r' => {
452            expect!(bytes.next() == b'\n' => Err(Error::Status));
453            bytes.slice();
454            ""
455        }
456        b'\n' => {
457            bytes.slice();
458            ""
459        }
460        _ => return Err(Error::Status),
461    };
462
463    Ok(Status::Complete((bytes.slice_pos(), version, code, reason)))
464}
465
466/// Represents a parsed header.
467#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
468pub struct Header {
469    /// The name portion of a header.
470    ///
471    /// A header name must be valid ASCII-US, so it's safe to store as a `&str`.
472    pub name_start: usize,
473    pub name_end: usize,
474    /// The value portion of a header.
475    ///
476    /// While headers **should** be ASCII-US, the specification allows for
477    /// values that may not be, and so the value is stored as bytes.
478    pub value_start: usize,
479    pub value_end: usize,
480}
481
482#[inline]
483#[allow(missing_docs)]
484// WARNING: Exported for internal benchmarks, not fit for public consumption
485pub fn parse_version<'a>(bytes: &mut Bytes<'a>) -> Result<u8> {
486    if let Some(eight) = bytes.peek_n::<[u8; 8]>(8) {
487        const H10: u64 = u64::from_ne_bytes(*b"HTTP/1.0");
488        const H11: u64 = u64::from_ne_bytes(*b"HTTP/1.1");
489        // SAFETY: peek_n(8) before ensure within bounds
490        unsafe {
491            bytes.advance(8);
492        }
493        return match u64::from_ne_bytes(eight) {
494            H10 => Ok(Status::Complete(0)),
495            H11 => Ok(Status::Complete(1)),
496            _ => Err(Error::Version),
497        };
498    }
499
500    // else (but not in `else` because of borrow checker)
501
502    // If there aren't at least 8 bytes, we still want to detect early
503    // if this is a valid version or not. If it is, we'll return Partial.
504    expect!(bytes.next() == b'H' => Err(Error::Version));
505    expect!(bytes.next() == b'T' => Err(Error::Version));
506    expect!(bytes.next() == b'T' => Err(Error::Version));
507    expect!(bytes.next() == b'P' => Err(Error::Version));
508    expect!(bytes.next() == b'/' => Err(Error::Version));
509    expect!(bytes.next() == b'1' => Err(Error::Version));
510    expect!(bytes.next() == b'.' => Err(Error::Version));
511    Ok(Status::Partial)
512}
513
514#[inline]
515#[doc(hidden)]
516#[allow(missing_docs)]
517// WARNING: Exported for internal benchmarks, not fit for public consumption
518fn parse_method<'a>(mut bytes: &mut Bytes<'a>) -> Result<&'a str> {
519    complete!(skip_empty_lines(bytes));
520
521    const GET: [u8; 4] = *b"GET ";
522    const POST: [u8; 4] = *b"POST";
523    match bytes.peek_n::<[u8; 4]>(4) {
524        Some(GET) => {
525            // SAFETY: we matched "GET " which has 4 bytes and is ASCII
526            let method = unsafe {
527                bytes.advance(4); // advance cursor past "GET "
528                str::from_utf8_unchecked(bytes.slice_skip(1)) // "GET" without space
529            };
530            complete!(skip_spaces(bytes));
531            Ok(Status::Complete(method))
532        }
533        // SAFETY:
534        // If `bytes.peek_n...` returns a Some([u8; 4]),
535        // then we are assured that `bytes` contains at least 4 bytes.
536        // Thus `bytes.len() >= 4`,
537        // and it is safe to peek at byte 4 with `bytes.peek_ahead(4)`.
538        Some(POST) if unsafe { bytes.peek_ahead(4) } == Some(b' ') => {
539            // SAFETY: we matched "POST " which has 5 bytes
540            let method = unsafe {
541                bytes.advance(5); // advance cursor past "POST "
542                str::from_utf8_unchecked(bytes.slice_skip(1)) // "POST" without space
543            };
544            complete!(skip_spaces(bytes));
545            Ok(Status::Complete(method))
546        }
547        _ => parse_token(&mut bytes),
548    }
549}
550
551/// From [RFC 7230](https://tools.ietf.org/html/rfc7230):
552///
553/// > ```notrust
554/// > reason-phrase  = *( HTAB / SP / VCHAR / obs-text )
555/// > HTAB           = %x09        ; horizontal tab
556/// > VCHAR          = %x21-7E     ; visible (printing) characters
557/// > obs-text       = %x80-FF
558/// > ```
559///
560/// > A.2.  Changes from RFC 2616
561/// >
562/// > Non-US-ASCII content in header fields and the reason phrase
563/// > has been obsoleted and made opaque (the TEXT rule was removed).
564#[inline]
565fn parse_reason<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
566    let mut seen_obs_text = false;
567    loop {
568        let b = next!(bytes);
569        if b == b'\r' {
570            expect!(bytes.next() == b'\n' => Err(Error::Status));
571            return Ok(Status::Complete(
572                // SAFETY: (1) calling bytes.slice_skip(2) is safe, because at least two next! calls
573                // advance the bytes iterator.
574                // (2) calling from_utf8_unchecked is safe, because the bytes returned by slice_skip
575                // were validated to be allowed US-ASCII chars by the other arms of the if/else or
576                // otherwise `seen_obs_text` is true and an empty string is returned instead.
577                unsafe {
578                    let bytes = bytes.slice_skip(2);
579                    if !seen_obs_text {
580                        // all bytes up till `i` must have been HTAB / SP / VCHAR
581                        str::from_utf8_unchecked(bytes)
582                    } else {
583                        // obs-text characters were found, so return the fallback empty string
584                        ""
585                    }
586                },
587            ));
588        } else if b == b'\n' {
589            return Ok(Status::Complete(
590                // SAFETY: (1) calling bytes.slice_skip(1) is safe, because at least one next! call
591                // advance the bytes iterator.
592                // (2) see (2) of safety comment above.
593                unsafe {
594                    let bytes = bytes.slice_skip(1);
595                    if !seen_obs_text {
596                        // all bytes up till `i` must have been HTAB / SP / VCHAR
597                        str::from_utf8_unchecked(bytes)
598                    } else {
599                        // obs-text characters were found, so return the fallback empty string
600                        ""
601                    }
602                },
603            ));
604        } else if !(b == 0x09 || b == b' ' || (0x21..=0x7E).contains(&b) || b >= 0x80) {
605            return Err(Error::Status);
606        } else if b >= 0x80 {
607            seen_obs_text = true;
608        }
609    }
610}
611
612#[inline]
613fn parse_token<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
614    let b = next!(bytes);
615    if !is_method_token(b) {
616        // First char must be a token char, it can't be a space which would indicate an empty token.
617        return Err(Error::Token);
618    }
619
620    loop {
621        let b = next!(bytes);
622        if b == b' ' {
623            return Ok(Status::Complete(
624                // SAFETY: all bytes up till `i` must have been `is_method_token` and therefore also utf-8.
625                unsafe { str::from_utf8_unchecked(bytes.slice_skip(1)) },
626            ));
627        } else if !is_method_token(b) {
628            return Err(Error::Token);
629        }
630    }
631}
632
633#[inline]
634#[allow(missing_docs)]
635// WARNING: Exported for internal benchmarks, not fit for public consumption
636fn parse_uri<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
637    let start = bytes.pos();
638    simd::match_uri_vectored(bytes);
639    let end = bytes.pos();
640
641    if next!(bytes) == b' ' {
642        // URI must have at least one char
643        if end == start {
644            return Err(Error::Token);
645        }
646
647        // SAFETY: all bytes up till `i` must have been `is_token` and therefore also utf-8.
648        match str::from_utf8(unsafe { bytes.slice_skip(1) }) {
649            Ok(uri) => {
650                complete!(skip_spaces(bytes));
651                Ok(Status::Complete(uri))
652            }
653            Err(_) => Err(Error::Token),
654        }
655    } else {
656        Err(Error::Token)
657    }
658}
659
660#[inline]
661fn parse_code(bytes: &mut Bytes<'_>) -> Result<u16> {
662    let hundreds = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
663    let tens = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
664    let ones = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
665
666    Ok(Status::Complete(
667        (hundreds - b'0') as u16 * 100 + (tens - b'0') as u16 * 10 + (ones - b'0') as u16,
668    ))
669}
670
671/// Parse a buffer of bytes as headers.
672///
673/// The return value, if complete and successful, includes the index of the
674/// buffer that parsing stopped at, and a sliced reference to the parsed
675/// headers. The length of the slice will be equal to the number of properly
676/// parsed headers.
677///
678/// # Example
679///
680/// ```
681/// let buf = b"Host: foo.bar\nAccept: */*\n\nblah blah";
682/// let mut headers = [httparse::EMPTY_HEADER; 4];
683/// assert_eq!(httparse::parse_headers(buf, &mut headers),
684///            Ok(httparse::Status::Complete((27, &[
685///                httparse::Header { name: "Host", value: b"foo.bar" },
686///                httparse::Header { name: "Accept", value: b"*/*" }
687///            ][..]))));
688/// ```
689pub fn parse_header(src: &[u8]) -> Result<(usize, Option<Header>)> {
690    let mut bytes = Bytes::new(src);
691    parse_header_iter_uninit(&mut bytes, &HeaderParserConfig::default())
692}
693
694#[derive(Clone, Debug, Default)]
695struct HeaderParserConfig {
696    allow_spaces_after_header_name: bool,
697    allow_obsolete_multiline_headers: bool,
698}
699
700/* Function which parsers headers into uninitialized buffer.
701 *
702 * Guarantees that it doesn't write garbage, so casting
703 * &mut &mut [Header] -> &mut &mut [MaybeUninit<Header>]
704 * is safe here.
705 *
706 * Also it promises `headers` get shrunk to number of initialized headers,
707 * so casting the other way around after calling this function is safe
708 */
709fn parse_header_iter_uninit<'a>(
710    bytes: &mut Bytes<'a>,
711    config: &HeaderParserConfig,
712) -> Result<(usize, Option<Header>)> {
713    // Track starting pointer to calculate the number of bytes parsed.
714    let start = bytes.as_ref().as_ptr() as usize;
715    let mut header = Header::default();
716
717    macro_rules! maybe_continue_after_obsolete_line_folding {
718        ($bytes:ident, $label:lifetime) => {
719            if config.allow_obsolete_multiline_headers {
720                match $bytes.peek() {
721                    None => {
722                        // Next byte may be a space, in which case that header
723                        // is using obsolete line folding, so we may have more
724                        // whitespace to skip after colon.
725                        return Ok(Status::Partial);
726                    }
727                    Some(b' ') | Some(b'\t') => {
728                        // The space will be consumed next iteration.
729                        continue $label;
730                    }
731                    _ => {
732                        // There is another byte after the end of the line,
733                        // but it's not whitespace, so it's probably another
734                        // header or the final line return. This header is thus
735                        // empty.
736                    },
737                }
738            }
739        }
740    }
741
742    loop {
743        // Return the error `$err` if `ignore_invalid_headers_in_responses`
744        // is false, otherwise find the end of the current line and resume
745        // parsing on the next one.
746        macro_rules! handle_invalid_char {
747            ($bytes:ident, $b:ident, $err:ident) => {
748                return Err(Error::$err);
749            };
750        }
751
752        // a newline here means the head is over!
753        let b = next!(bytes);
754        if b == b'\r' {
755            expect!(bytes.next() == b'\n' => Err(Error::NewLine));
756            let end = bytes.as_ref().as_ptr() as usize;
757            return Ok(Status::Complete((end - start, None)));
758        }
759        if b == b'\n' {
760            let end = bytes.as_ref().as_ptr() as usize;
761            return Ok(Status::Complete((end - start, None)));
762        }
763        if !is_header_name_token(b) {
764            handle_invalid_char!(bytes, b, HeaderName);
765        }
766
767        header.name_start = bytes.slice_pos() - 1;
768
769        #[allow(clippy::never_loop)]
770        // parse header name until colon
771        'name: loop {
772            simd::match_header_name_vectored(bytes);
773            let mut b = next!(bytes);
774
775            // SAFETY: previously bumped by 1 with next! -> always safe.
776            header.name_end = bytes.slice_pos() - 1;
777            bytes.commit();
778
779            if b == b':' {
780                break 'name;
781            }
782
783            if config.allow_spaces_after_header_name {
784                while b == b' ' || b == b'\t' {
785                    b = next!(bytes);
786
787                    if b == b':' {
788                        bytes.commit();
789                        break 'name;
790                    }
791                }
792            }
793
794            handle_invalid_char!(bytes, b, HeaderName);
795        }
796
797        let mut b;
798
799        #[allow(clippy::never_loop)]
800        let value_slice = 'value: loop {
801            // eat white space between colon and value
802            'whitespace_after_colon: loop {
803                b = next!(bytes);
804                if b == b' ' || b == b'\t' {
805                    bytes.slice();
806                    continue 'whitespace_after_colon;
807                }
808                if is_header_value_token(b) {
809                    break 'whitespace_after_colon;
810                }
811
812                if b == b'\r' {
813                    expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
814                } else if b != b'\n' {
815                    handle_invalid_char!(bytes, b, HeaderValue);
816                }
817
818                maybe_continue_after_obsolete_line_folding!(bytes, 'whitespace_after_colon);
819
820                let whitespace_slice = bytes.slice();
821
822                // This produces an empty slice that points to the beginning
823                // of the whitespace.
824                break 'value &whitespace_slice[0..0];
825            }
826
827            header.value_start = bytes.slice_pos() - 1;
828
829            'value_lines: loop {
830                // parse value till EOL
831
832                simd::match_header_value_vectored(bytes);
833                let b = next!(bytes);
834
835                //found_ctl
836                let skip = if b == b'\r' {
837                    expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
838                    2
839                } else if b == b'\n' {
840                    1
841                } else {
842                    handle_invalid_char!(bytes, b, HeaderValue);
843                };
844
845                maybe_continue_after_obsolete_line_folding!(bytes, 'value_lines);
846
847                // SAFETY: having just checked that a newline exists, it's safe to skip it.
848                unsafe {
849                    break 'value bytes.slice_skip(skip);
850                }
851            }
852        };
853
854        header.value_end = bytes.slice_pos();
855
856        // trim trailing whitespace in the header
857        if let Some(last_visible) = value_slice
858            .iter()
859            .rposition(|b| *b != b' ' && *b != b'\t' && *b != b'\r' && *b != b'\n')
860        {
861            header.value_end = header.value_start + last_visible + 1;
862        }
863
864        return Ok(Status::Complete((bytes.slice_pos(), Some(header))));
865    }
866}
867
868/// Parse a buffer of bytes as a chunk size.
869///
870/// The return value, if complete and successful, includes the index of the
871/// buffer that parsing stopped at, and the size of the following chunk.
872///
873/// # Example
874///
875/// ```
876/// let buf = b"4\r\nRust\r\n0\r\n\r\n";
877/// assert_eq!(httparse::parse_chunk_size(buf),
878///            Ok(httparse::Status::Complete((3, 4))));
879/// ```
880pub fn parse_chunk_size(buf: &[u8]) -> result::Result<Status<(usize, u64)>, InvalidChunkSize> {
881    const RADIX: u64 = 16;
882    let mut bytes = Bytes::new(buf);
883    let mut size = 0;
884    let mut in_chunk_size = true;
885    let mut in_ext = false;
886    let mut count = 0;
887    loop {
888        let b = next!(bytes);
889        match b {
890            b'0'..=b'9' if in_chunk_size => {
891                if count > 15 {
892                    return Err(InvalidChunkSize);
893                }
894                count += 1;
895                if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
896                    // actually unreachable!(), because count stops the loop at 15 digits before
897                    // we can reach u64::MAX / RADIX == 0xfffffffffffffff, which requires 15 hex
898                    // digits. This stops mirai reporting a false alarm regarding the `size *=
899                    // RADIX` multiplication below.
900                    return Err(InvalidChunkSize);
901                }
902                size *= RADIX;
903                size += (b - b'0') as u64;
904            }
905            b'a'..=b'f' | b'A'..=b'F' if in_chunk_size => {
906                if count > 15 {
907                    return Err(InvalidChunkSize);
908                }
909                count += 1;
910                if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
911                    return Err(InvalidChunkSize);
912                }
913                size *= RADIX;
914                size += ((b | 0x20) + 10 - b'a') as u64;
915            }
916            b'\r' => match next!(bytes) {
917                b'\n' => break,
918                _ => return Err(InvalidChunkSize),
919            },
920            // If we weren't in the extension yet, the ";" signals its start
921            b';' if !in_ext => {
922                in_ext = true;
923                in_chunk_size = false;
924            }
925            // "Linear white space" is ignored between the chunk size and the
926            // extension separator token (";") due to the "implied *LWS rule".
927            b'\t' | b' ' if !in_ext && !in_chunk_size => {}
928            // LWS can follow the chunk size, but no more digits can come
929            b'\t' | b' ' if in_chunk_size => in_chunk_size = false,
930            // We allow any arbitrary octet once we are in the extension, since
931            // they all get ignored anyway. According to the HTTP spec, valid
932            // extensions would have a more strict syntax:
933            //     (token ["=" (token | quoted-string)])
934            // but we gain nothing by rejecting an otherwise valid chunk size.
935            _ if in_ext => {}
936            // Finally, if we aren't in the extension and we're reading any
937            // other octet, the chunk size line is invalid!
938            _ => return Err(InvalidChunkSize),
939        }
940    }
941    Ok(Status::Complete((bytes.slice_pos(), size)))
942}
943
944#[cfg(test)]
945mod tests {
946    use super::{parse_request, Error, Status};
947
948    const NUM_OF_HEADERS: usize = 4;
949
950    macro_rules! req {
951        ($name:ident, $buf:expr, |($method:ident, $path:ident, $version:ident, $headers:ident)| $body:expr) => {
952            req! {$name, $buf, Ok(Status::Complete(item)), |($method, $path, $version, $headers)| $body }
953        };
954        ($name:ident, $buf:expr, $len:expr, |($method:ident, $path:ident, $version:ident, $headers:ident)| $body:expr) => {
955            #[test]
956            fn $name() {
957                // let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
958                let status = parse_request($buf.as_ref());
959                let (_, m, p, v) = if let $len = parse_request($buf.as_ref()) {
960                    item
961                } else {
962                    panic!()
963                };
964                closure((m, p, v, Vec::new()));
965
966                fn closure(($method, $path, $version, $headers): (&str, &str, u8, Vec<(String, Vec<u8>)>)) {
967                    $body
968                }
969            }
970        };
971    }
972
973    req! {
974        test_request_simple,
975        b"GET / HTTP/1.1\r\n\r\n",
976        |(method, path, version, headers)| {
977            assert_eq!(method, "GET");
978            assert_eq!(path, "/");
979            assert_eq!(version, 1);
980            assert_eq!(headers.len(), 0);
981        }
982    }
983
984    req! {
985        test_request_simple_with_query_params,
986        b"GET /thing?data=a HTTP/1.1\r\n\r\n",
987        |(method, path, version, headers)| {
988            assert_eq!(method, "GET");
989            assert_eq!(path, "/thing?data=a");
990            assert_eq!(version, 1);
991            assert_eq!(headers.len(), 0);
992        }
993    }
994
995    req! {
996        test_request_simple_with_whatwg_query_params,
997        b"GET /thing?data=a^ HTTP/1.1\r\n\r\n",
998        |(method, path, version, headers)| {
999            assert_eq!(method, "GET");
1000            assert_eq!(path, "/thing?data=a^");
1001            assert_eq!(version, 1);
1002            assert_eq!(headers.len(), 0);
1003        }
1004    }
1005
1006    req! {
1007        test_request_headers,
1008        b"GET / HTTP/1.1\r\nHost: foo.com\r\nCookie: \r\n\r\n",
1009        |(method, path, version, headers)| {
1010            assert_eq!(method, "GET");
1011            assert_eq!(path, "/");
1012            assert_eq!(version, 1);
1013            assert_eq!(headers.len(), 2);
1014            assert_eq!(headers[0].0, "Host");
1015            assert_eq!(headers[0].1, b"foo.com");
1016            assert_eq!(headers[1].0, "Cookie");
1017            assert_eq!(headers[1].1, b"");
1018        }
1019    }
1020
1021    req! {
1022        test_request_headers_optional_whitespace,
1023        b"GET / HTTP/1.1\r\nHost: \tfoo.com\t \r\nCookie: \t \r\n\r\n",
1024        |(method, path, version, headers)| {
1025            assert_eq!(method, "GET");
1026            assert_eq!(path, "/");
1027            assert_eq!(version, 1);
1028            assert_eq!(headers.len(), 2);
1029            assert_eq!(headers[0].0, "Host");
1030            assert_eq!(headers[0].1, b"foo.com");
1031            assert_eq!(headers[1].0, "Cookie");
1032            assert_eq!(headers[1].1, b"");
1033        }
1034    }
1035
1036    req! {
1037        // test the scalar parsing
1038        test_request_header_value_htab_short,
1039        b"GET / HTTP/1.1\r\nUser-Agent: some\tagent\r\n\r\n",
1040        |(method, path, version, headers)| {
1041            assert_eq!(method, "GET");
1042            assert_eq!(path, "/");
1043            assert_eq!(version, 1);
1044            assert_eq!(headers.len(), 1);
1045            assert_eq!(headers[0].0, "User-Agent");
1046            assert_eq!(headers[0].1, b"some\tagent");
1047        }
1048    }
1049
1050    req! {
1051        // test the sse42 parsing
1052        test_request_header_value_htab_med,
1053        b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\tagent\r\n\r\n",
1054        |(method, path, version, headers)| {
1055            assert_eq!(method, "GET");
1056            assert_eq!(path, "/");
1057            assert_eq!(version, 1);
1058            assert_eq!(headers.len(), 1);
1059            assert_eq!(headers[0].0, "User-Agent");
1060            assert_eq!(headers[0].1, b"1234567890some\tagent");
1061        }
1062    }
1063
1064    req! {
1065        // test the avx2 parsing
1066        test_request_header_value_htab_long,
1067        b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\t1234567890agent1234567890\r\n\r\n",
1068        |(method, path, version, headers)| {
1069            assert_eq!(method, "GET");
1070            assert_eq!(path, "/");
1071            assert_eq!(version, 1);
1072            assert_eq!(headers.len(), 1);
1073            assert_eq!(headers[0].0, "User-Agent");
1074            assert_eq!(headers[0].1, &b"1234567890some\t1234567890agent1234567890"[..]);
1075        }
1076    }
1077
1078    req! {
1079        // test the avx2 parsing
1080        test_request_header_no_space_after_colon,
1081        b"GET / HTTP/1.1\r\nUser-Agent:omg-no-space1234567890some1234567890agent1234567890\r\n\r\n",
1082        |(method, path, version, headers)| {
1083            assert_eq!(method, "GET");
1084            assert_eq!(path, "/");
1085            assert_eq!(version, 1);
1086            assert_eq!(headers.len(), 1);
1087            assert_eq!(headers[0].0, "User-Agent");
1088            assert_eq!(headers[0].1, &b"omg-no-space1234567890some1234567890agent1234567890"[..]);
1089        }
1090    }
1091
1092    req! {
1093        test_request_headers_max,
1094        b"GET / HTTP/1.1\r\nA: A\r\nB: B\r\nC: C\r\nD: D\r\n\r\n",
1095        |(_method, _path, _verion, headers)| {
1096            assert_eq!(headers.len(), NUM_OF_HEADERS);
1097        }
1098    }
1099
1100    req! {
1101        test_request_multibyte,
1102        b"GET / HTTP/1.1\r\nHost: foo.com\r\nUser-Agent: \xe3\x81\xb2\xe3/1.0\r\n\r\n",
1103        |(method, path, version, headers)| {
1104            assert_eq!(method, "GET");
1105            assert_eq!(path, "/");
1106            assert_eq!(version, 1);
1107            assert_eq!(headers.len(), 2);
1108            assert_eq!(headers[0].0, "Host");
1109            assert_eq!(headers[0].1, b"foo.com");
1110            assert_eq!(headers[1].0, "User-Agent");
1111            assert_eq!(headers[1].1, b"\xe3\x81\xb2\xe3/1.0");
1112        }
1113    }
1114
1115    // A single byte which is part of a method is not invalid
1116    req! {
1117        test_request_one_byte_method,
1118        b"G", Ok(Status::Partial),
1119        |(_method, _path, _verion, _headers)| {}
1120    }
1121
1122    // A subset of a method is a partial method, not invalid
1123    req! {
1124        test_request_partial_method,
1125        b"GE", Ok(Status::Partial),
1126        |(_method, _path, _verion, _headers)| {}
1127    }
1128
1129    // A method, without the delimiting space, is a partial request
1130    req! {
1131        test_request_method_no_delimiter,
1132        b"GET", Ok(Status::Partial),
1133        |(_method, _path, _verion, _headers)| {}
1134    }
1135
1136    // Regression test: assert that a partial read with just the method and
1137    // space results in a partial, rather than a token error from uri parsing.
1138    req! {
1139        test_request_method_only,
1140        b"GET ", Ok(Status::Partial),
1141        |(_method, _path, _verion, _headers)| {}
1142    }
1143
1144    req! {
1145        test_request_partial,
1146        b"GET / HTTP/1.1\r\n\r", Ok(Status::Partial),
1147        |(_method, _path, _verion, _headers)| {}
1148    }
1149
1150    req! {
1151        test_request_partial_version,
1152        b"GET / HTTP/1.", Ok(Status::Partial),
1153        |(_method, _path, _verion, _headers)| {}
1154    }
1155
1156    req! {
1157        test_request_method_path_no_delimiter,
1158        b"GET /", Ok(Status::Partial),
1159        |(_method, _path, _verion, _headers)| {}
1160    }
1161
1162    req! {
1163        test_request_method_path_only,
1164        b"GET / ", Ok(Status::Partial),
1165        |(_method, _path, _verion, _headers)| {}
1166    }
1167
1168    req! {
1169        test_request_partial_parses_headers_as_much_as_it_can,
1170        b"GET / HTTP/1.1\r\nHost: yolo\r\n",
1171        Ok(crate::Status::Partial),
1172        |(method, path, version, headers)| {
1173            assert_eq!(method, "GET");
1174            assert_eq!(path, "/");
1175            assert_eq!(version, 1);
1176            assert_eq!(headers.len(), NUM_OF_HEADERS); // doesn't slice since not Complete
1177            assert_eq!(headers[0].0, "Host");
1178            assert_eq!(headers[0].1, b"yolo");
1179        }
1180    }
1181
1182    req! {
1183        test_request_newlines,
1184        b"GET / HTTP/1.1\nHost: foo.bar\n\n",
1185        |(_method, _path, _verion, _headers)| {}
1186    }
1187
1188    req! {
1189        test_request_empty_lines_prefix,
1190        b"\r\n\r\nGET / HTTP/1.1\r\n\r\n",
1191        |(method, path, version, headers)| {
1192            assert_eq!(method, "GET");
1193            assert_eq!(path, "/");
1194            assert_eq!(version, 1);
1195            assert_eq!(headers.len(), 0);
1196        }
1197    }
1198
1199    req! {
1200        test_request_empty_lines_prefix_lf_only,
1201        b"\n\nGET / HTTP/1.1\n\n",
1202        |(method, path, version, headers)| {
1203            assert_eq!(method, "GET");
1204            assert_eq!(path, "/");
1205            assert_eq!(version, 1);
1206            assert_eq!(headers.len(), 0);
1207        }
1208    }
1209
1210    req! {
1211        test_request_path_backslash,
1212        b"\n\nGET /\\?wayne\\=5 HTTP/1.1\n\n",
1213        |(method, path, version, headers)| {
1214            assert_eq!(method, "GET");
1215            assert_eq!(path, "/\\?wayne\\=5");
1216            assert_eq!(version, 1);
1217            assert_eq!(headers.len(), 0);
1218        }
1219    }
1220
1221    req! {
1222        test_request_with_invalid_token_delimiter,
1223        b"GET\n/ HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
1224        Err(crate::Error::Token),
1225        |(_method, _path, _verion, _headers)| {}
1226    }
1227
1228    req! {
1229        test_request_with_invalid_but_short_version,
1230        b"GET / HTTP/1!",
1231        Err(crate::Error::Version),
1232        |(_method, _path, _verion, _headers)| {}
1233    }
1234
1235    req! {
1236        test_request_with_empty_method,
1237        b" / HTTP/1.1\r\n\r\n",
1238        Err(crate::Error::Token),
1239        |(_method, _path, _verion, _headers)| {}
1240    }
1241
1242    req! {
1243        test_request_with_empty_path,
1244        b"GET  HTTP/1.1\r\n\r\n",
1245        Err(crate::Error::Token),
1246        |(_method, _path, _verion, _headers)| {}
1247    }
1248
1249    req! {
1250        test_request_with_empty_method_and_path,
1251        b"  HTTP/1.1\r\n\r\n",
1252        Err(crate::Error::Token),
1253        |(_method, _path, _verion, _headers)| {}
1254    }
1255
1256    // macro_rules! res {
1257    //     ($name:ident, $buf:expr, |$arg:ident| $body:expr) => {
1258    //         res! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
1259    //     };
1260    //     ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => {
1261    //         #[test]
1262    //         fn $name() {
1263    //             let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1264    //             let mut res = Response::new(&mut headers[..]);
1265    //             let status = res.parse($buf.as_ref());
1266    //             assert_eq!(status, $len);
1267    //             closure(res);
1268
1269    //             fn closure($arg: Response) {
1270    //                 $body
1271    //             }
1272    //         }
1273    //     };
1274    // }
1275
1276    // res! {
1277    //     test_response_simple,
1278    //     b"HTTP/1.1 200 OK\r\n\r\n",
1279    //     |version, code, reason| {
1280    //         assert_eq!(res.version.unwrap(), 1);
1281    //         assert_eq!(res.code.unwrap(), 200);
1282    //         assert_eq!(res.reason.unwrap(), "OK");
1283    //     }
1284    // }
1285
1286    // res! {
1287    //     test_response_newlines,
1288    //     b"HTTP/1.0 403 Forbidden\nServer: foo.bar\n\n",
1289    //     |_version, _code, _reason| {}
1290    // }
1291
1292    // res! {
1293    //     test_response_reason_missing,
1294    //     b"HTTP/1.1 200 \r\n\r\n",
1295    //     |version, code, reason| {
1296    //         assert_eq!(res.version.unwrap(), 1);
1297    //         assert_eq!(res.code.unwrap(), 200);
1298    //         assert_eq!(res.reason.unwrap(), "");
1299    //     }
1300    // }
1301
1302    // res! {
1303    //     test_response_reason_missing_no_space,
1304    //     b"HTTP/1.1 200\r\n\r\n",
1305    //     |version, code, reason| {
1306    //         assert_eq!(res.version.unwrap(), 1);
1307    //         assert_eq!(res.code.unwrap(), 200);
1308    //         assert_eq!(res.reason.unwrap(), "");
1309    //     }
1310    // }
1311
1312    // res! {
1313    //     test_response_reason_missing_no_space_with_headers,
1314    //     b"HTTP/1.1 200\r\nFoo: bar\r\n\r\n",
1315    //     |version, code, reason| {
1316    //         assert_eq!(res.version.unwrap(), 1);
1317    //         assert_eq!(res.code.unwrap(), 200);
1318    //         assert_eq!(res.reason.unwrap(), "");
1319    //         assert_eq!(res.headers.len(), 1);
1320    //         assert_eq!(res.headers[0].0, "Foo");
1321    //         assert_eq!(res.headers[0].1, b"bar");
1322    //     }
1323    // }
1324
1325    // res! {
1326    //     test_response_reason_with_space_and_tab,
1327    //     b"HTTP/1.1 101 Switching Protocols\t\r\n\r\n",
1328    //     |version, code, reason| {
1329    //         assert_eq!(res.version.unwrap(), 1);
1330    //         assert_eq!(res.code.unwrap(), 101);
1331    //         assert_eq!(res.reason.unwrap(), "Switching Protocols\t");
1332    //     }
1333    // }
1334
1335    // static RESPONSE_REASON_WITH_OBS_TEXT_BYTE: &[u8] = b"HTTP/1.1 200 X\xFFZ\r\n\r\n";
1336    // res! {
1337    //     test_response_reason_with_obsolete_text_byte,
1338    //     RESPONSE_REASON_WITH_OBS_TEXT_BYTE,
1339    //     |version, code, reason| {
1340    //         assert_eq!(res.version.unwrap(), 1);
1341    //         assert_eq!(res.code.unwrap(), 200);
1342    //         // Empty string fallback in case of obs-text
1343    //         assert_eq!(res.reason.unwrap(), "");
1344    //     }
1345    // }
1346
1347    // res! {
1348    //     test_response_reason_with_nul_byte,
1349    //     b"HTTP/1.1 200 \x00\r\n\r\n",
1350    //     Err(crate::Error::Status),
1351    //     |_version, _code, _reason| {}
1352    // }
1353
1354    // res! {
1355    //     test_response_version_missing_space,
1356    //     b"HTTP/1.1",
1357    //     Ok(Status::Partial),
1358    //     |_version, _code, _reason| {}
1359    //     |_res| {}
1360    // }
1361
1362    // res! {
1363    //     test_response_code_missing_space,
1364    //     b"HTTP/1.1 200",
1365    //     Ok(Status::Partial),
1366    //     |_version, _code, _reason| {}
1367    // }
1368
1369    // res! {
1370    //     test_response_partial_parses_headers_as_much_as_it_can,
1371    //     b"HTTP/1.1 200 OK\r\nServer: yolo\r\n",
1372    //     Ok(crate::Status::Partial),
1373    //     |version, code, reason| {
1374    //         assert_eq!(res.version.unwrap(), 1);
1375    //         assert_eq!(res.code.unwrap(), 200);
1376    //         assert_eq!(res.reason.unwrap(), "OK");
1377    //         assert_eq!(res.headers.len(), NUM_OF_HEADERS); // doesn't slice since not Complete
1378    //         assert_eq!(res.headers[0].0, "Server");
1379    //         assert_eq!(res.headers[0].1, b"yolo");
1380    //     }
1381    // }
1382
1383    // res! {
1384    //     test_response_empty_lines_prefix_lf_only,
1385    //     b"\n\nHTTP/1.1 200 OK\n\n",
1386    //     |_version, _code, _reason| {}
1387    // }
1388
1389    // res! {
1390    //     test_response_no_cr,
1391    //     b"HTTP/1.0 200\nContent-type: text/html\n\n",
1392    //     |version, code, reason| {
1393    //         assert_eq!(res.version.unwrap(), 0);
1394    //         assert_eq!(res.code.unwrap(), 200);
1395    //         assert_eq!(res.reason.unwrap(), "");
1396    //         assert_eq!(res.headers.len(), 1);
1397    //         assert_eq!(res.headers[0].0, "Content-type");
1398    //         assert_eq!(res.headers[0].1, b"text/html");
1399    //     }
1400    // }
1401
1402    // /// Check all subset permutations of a partial request line with no headers
1403    // #[test]
1404    // fn partial_permutations() {
1405    //     let req_str = "GET / HTTP/1.1\r\n\r\n";
1406    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1407    //     let mut req = Request::new(&mut headers[..]);
1408    //     for i in 0..req_str.len() {
1409    //         let status = req.parse(&req_str.as_bytes()[..i]);
1410    //         assert_eq!(
1411    //             status,
1412    //             Ok(Status::Partial),
1413    //             "partial request line should return partial. \
1414    //              Portion which failed: '{seg}' (below {i})",
1415    //             seg = &req_str[..i]
1416    //         );
1417    //     }
1418    // }
1419
1420    // static RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
1421    //     b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\nBread: baguette\r\n\r\n";
1422
1423    // #[test]
1424    // fn test_forbid_response_with_whitespace_between_header_name_and_colon() {
1425    //     let mut headers = [EMPTY_HEADER; 2];
1426    //     let mut response = Response::new(&mut headers[..]);
1427    //     let result = response.parse(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1428
1429    //     assert_eq!(result, Err(crate::Error::HeaderName));
1430    // }
1431
1432    // #[test]
1433    // fn test_allow_response_with_whitespace_between_header_name_and_colon() {
1434    //     let mut headers = [EMPTY_HEADER; 2];
1435    //     let mut response = Response::new(&mut headers[..]);
1436    //     let result = crate::ParserConfig::default()
1437    //         .allow_spaces_after_header_name_in_responses(true)
1438    //         .parse_response(
1439    //             &mut response,
1440    //             RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON,
1441    //         );
1442
1443    //     assert_eq!(result, Ok(Status::Complete(77)));
1444    //     assert_eq!(response.version.unwrap(), 1);
1445    //     assert_eq!(response.code.unwrap(), 200);
1446    //     assert_eq!(response.reason.unwrap(), "OK");
1447    //     assert_eq!(response.headers.len(), 2);
1448    //     assert_eq!(response.headers[0].0, "Access-Control-Allow-Credentials");
1449    //     assert_eq!(response.headers[0].1, &b"true"[..]);
1450    //     assert_eq!(response.headers[1].0, "Bread");
1451    //     assert_eq!(response.headers[1].1, &b"baguette"[..]);
1452    // }
1453
1454    // #[test]
1455    // fn test_ignore_header_line_with_whitespaces_after_header_name_in_response() {
1456    //     let mut headers = [EMPTY_HEADER; 2];
1457    //     let mut response = Response::new(&mut headers[..]);
1458    //     let result = crate::ParserConfig::default()
1459    //         .ignore_invalid_headers_in_responses(true)
1460    //         .parse_response(
1461    //             &mut response,
1462    //             RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON,
1463    //         );
1464
1465    //     assert_eq!(result, Ok(Status::Complete(77)));
1466    //     assert_eq!(response.version.unwrap(), 1);
1467    //     assert_eq!(response.code.unwrap(), 200);
1468    //     assert_eq!(response.reason.unwrap(), "OK");
1469    //     assert_eq!(response.headers.len(), 1);
1470    //     assert_eq!(response.headers[0].0, "Bread");
1471    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
1472    // }
1473
1474    // static REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
1475    //     b"GET / HTTP/1.1\r\nHost : localhost\r\n\r\n";
1476
1477    // #[test]
1478    // fn test_forbid_request_with_whitespace_between_header_name_and_colon() {
1479    //     let mut headers = [EMPTY_HEADER; 1];
1480    //     let mut request = Request::new(&mut headers[..]);
1481    //     let result = request.parse(REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1482
1483    //     assert_eq!(result, Err(crate::Error::HeaderName));
1484    // }
1485
1486    // #[test]
1487    // fn test_ignore_header_line_with_whitespaces_after_header_name_in_request() {
1488    //     let mut headers = [EMPTY_HEADER; 2];
1489    //     let mut request = Request::new(&mut headers[..]);
1490    //     let result = crate::ParserConfig::default()
1491    //         .ignore_invalid_headers_in_requests(true)
1492    //         .parse_request(
1493    //             &mut request,
1494    //             REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON,
1495    //         );
1496
1497    //     assert_eq!(result, Ok(Status::Complete(36)));
1498    // }
1499
1500    // static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START: &[u8] =
1501    //     b"HTTP/1.1 200 OK\r\nLine-Folded-Header: \r\n   \r\n hello there\r\n\r\n";
1502
1503    // #[test]
1504    // fn test_forbid_response_with_obsolete_line_folding_at_start() {
1505    //     let mut headers = [EMPTY_HEADER; 1];
1506    //     let mut response = Response::new(&mut headers[..]);
1507    //     let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
1508
1509    //     assert_eq!(result, Err(crate::Error::HeaderName));
1510    // }
1511
1512    // #[test]
1513    // fn test_allow_response_with_obsolete_line_folding_at_start() {
1514    //     let mut headers = [EMPTY_HEADER; 1];
1515    //     let mut response = Response::new(&mut headers[..]);
1516    //     let result = crate::ParserConfig::default()
1517    //         .allow_obsolete_multiline_headers_in_responses(true)
1518    //         .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
1519
1520    //     assert_eq!(
1521    //         result,
1522    //         Ok(Status::Complete(
1523    //             RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START.len()
1524    //         ))
1525    //     );
1526    //     assert_eq!(response.version.unwrap(), 1);
1527    //     assert_eq!(response.code.unwrap(), 200);
1528    //     assert_eq!(response.reason.unwrap(), "OK");
1529    //     assert_eq!(response.headers.len(), 1);
1530    //     assert_eq!(response.headers[0].0, "Line-Folded-Header");
1531    //     assert_eq!(response.headers[0].1, &b"hello there"[..]);
1532    // }
1533
1534    // static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END: &[u8] =
1535    //     b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello there\r\n   \r\n \r\n\r\n";
1536
1537    // #[test]
1538    // fn test_forbid_response_with_obsolete_line_folding_at_end() {
1539    //     let mut headers = [EMPTY_HEADER; 1];
1540    //     let mut response = Response::new(&mut headers[..]);
1541    //     let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
1542
1543    //     assert_eq!(result, Err(crate::Error::HeaderName));
1544    // }
1545
1546    // #[test]
1547    // fn test_allow_response_with_obsolete_line_folding_at_end() {
1548    //     let mut headers = [EMPTY_HEADER; 1];
1549    //     let mut response = Response::new(&mut headers[..]);
1550    //     let result = crate::ParserConfig::default()
1551    //         .allow_obsolete_multiline_headers_in_responses(true)
1552    //         .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
1553
1554    //     assert_eq!(
1555    //         result,
1556    //         Ok(Status::Complete(
1557    //             RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END.len()
1558    //         ))
1559    //     );
1560    //     assert_eq!(response.version.unwrap(), 1);
1561    //     assert_eq!(response.code.unwrap(), 200);
1562    //     assert_eq!(response.reason.unwrap(), "OK");
1563    //     assert_eq!(response.headers.len(), 1);
1564    //     assert_eq!(response.headers[0].0, "Line-Folded-Header");
1565    //     assert_eq!(response.headers[0].1, &b"hello there"[..]);
1566    // }
1567
1568    // static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE: &[u8] =
1569    //     b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello  \r\n \r\n there\r\n\r\n";
1570
1571    // #[test]
1572    // fn test_forbid_response_with_obsolete_line_folding_in_middle() {
1573    //     let mut headers = [EMPTY_HEADER; 1];
1574    //     let mut response = Response::new(&mut headers[..]);
1575    //     let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
1576
1577    //     assert_eq!(result, Err(crate::Error::HeaderName));
1578    // }
1579
1580    // #[test]
1581    // fn test_allow_response_with_obsolete_line_folding_in_middle() {
1582    //     let mut headers = [EMPTY_HEADER; 1];
1583    //     let mut response = Response::new(&mut headers[..]);
1584    //     let result = crate::ParserConfig::default()
1585    //         .allow_obsolete_multiline_headers_in_responses(true)
1586    //         .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
1587
1588    //     assert_eq!(
1589    //         result,
1590    //         Ok(Status::Complete(
1591    //             RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE.len()
1592    //         ))
1593    //     );
1594    //     assert_eq!(response.version.unwrap(), 1);
1595    //     assert_eq!(response.code.unwrap(), 200);
1596    //     assert_eq!(response.reason.unwrap(), "OK");
1597    //     assert_eq!(response.headers.len(), 1);
1598    //     assert_eq!(response.headers[0].0, "Line-Folded-Header");
1599    //     assert_eq!(response.headers[0].1, &b"hello  \r\n \r\n there"[..]);
1600    // }
1601
1602    // static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER: &[u8] =
1603    //     b"HTTP/1.1 200 OK\r\nLine-Folded-Header:   \r\n \r\n \r\n\r\n";
1604
1605    // #[test]
1606    // fn test_forbid_response_with_obsolete_line_folding_in_empty_header() {
1607    //     let mut headers = [EMPTY_HEADER; 1];
1608    //     let mut response = Response::new(&mut headers[..]);
1609    //     let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER);
1610
1611    //     assert_eq!(result, Err(crate::Error::HeaderName));
1612    // }
1613
1614    // #[test]
1615    // fn test_allow_response_with_obsolete_line_folding_in_empty_header() {
1616    //     let mut headers = [EMPTY_HEADER; 1];
1617    //     let mut response = Response::new(&mut headers[..]);
1618    //     let result = crate::ParserConfig::default()
1619    //         .allow_obsolete_multiline_headers_in_responses(true)
1620    //         .parse_response(
1621    //             &mut response,
1622    //             RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER,
1623    //         );
1624
1625    //     assert_eq!(
1626    //         result,
1627    //         Ok(Status::Complete(
1628    //             RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER.len()
1629    //         ))
1630    //     );
1631    //     assert_eq!(response.version.unwrap(), 1);
1632    //     assert_eq!(response.code.unwrap(), 200);
1633    //     assert_eq!(response.reason.unwrap(), "OK");
1634    //     assert_eq!(response.headers.len(), 1);
1635    //     assert_eq!(response.headers[0].0, "Line-Folded-Header");
1636    //     assert_eq!(response.headers[0].1, &b""[..]);
1637    // }
1638
1639    // #[test]
1640    // fn test_chunk_size() {
1641    //     assert_eq!(parse_chunk_size(b"0\r\n"), Ok(Status::Complete((3, 0))));
1642    //     assert_eq!(
1643    //         parse_chunk_size(b"12\r\nchunk"),
1644    //         Ok(Status::Complete((4, 18)))
1645    //     );
1646    //     assert_eq!(
1647    //         parse_chunk_size(b"3086d\r\n"),
1648    //         Ok(Status::Complete((7, 198765)))
1649    //     );
1650    //     assert_eq!(
1651    //         parse_chunk_size(b"3735AB1;foo bar*\r\n"),
1652    //         Ok(Status::Complete((18, 57891505)))
1653    //     );
1654    //     assert_eq!(
1655    //         parse_chunk_size(b"3735ab1 ; baz \r\n"),
1656    //         Ok(Status::Complete((16, 57891505)))
1657    //     );
1658    //     assert_eq!(parse_chunk_size(b"77a65\r"), Ok(Status::Partial));
1659    //     assert_eq!(parse_chunk_size(b"ab"), Ok(Status::Partial));
1660    //     assert_eq!(
1661    //         parse_chunk_size(b"567f8a\rfoo"),
1662    //         Err(crate::InvalidChunkSize)
1663    //     );
1664    //     assert_eq!(
1665    //         parse_chunk_size(b"567f8a\rfoo"),
1666    //         Err(crate::InvalidChunkSize)
1667    //     );
1668    //     assert_eq!(
1669    //         parse_chunk_size(b"567xf8a\r\n"),
1670    //         Err(crate::InvalidChunkSize)
1671    //     );
1672    //     assert_eq!(
1673    //         parse_chunk_size(b"ffffffffffffffff\r\n"),
1674    //         Ok(Status::Complete((18, u64::MAX)))
1675    //     );
1676    //     assert_eq!(
1677    //         parse_chunk_size(b"1ffffffffffffffff\r\n"),
1678    //         Err(crate::InvalidChunkSize)
1679    //     );
1680    //     assert_eq!(
1681    //         parse_chunk_size(b"Affffffffffffffff\r\n"),
1682    //         Err(crate::InvalidChunkSize)
1683    //     );
1684    //     assert_eq!(
1685    //         parse_chunk_size(b"fffffffffffffffff\r\n"),
1686    //         Err(crate::InvalidChunkSize)
1687    //     );
1688    // }
1689
1690    // static RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] = b"HTTP/1.1   200  OK\r\n\r\n";
1691
1692    // #[test]
1693    // fn test_forbid_response_with_multiple_space_delimiters() {
1694    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1695    //     let mut response = Response::new(&mut headers[..]);
1696    //     let result = response.parse(RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
1697
1698    //     assert_eq!(result, Err(crate::Error::Status));
1699    // }
1700
1701    // #[test]
1702    // fn test_allow_response_with_multiple_space_delimiters() {
1703    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1704    //     let mut response = Response::new(&mut headers[..]);
1705    //     let result = crate::ParserConfig::default()
1706    //         .allow_multiple_spaces_in_response_status_delimiters(true)
1707    //         .parse_response(&mut response, RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
1708
1709    //     assert_eq!(
1710    //         result,
1711    //         Ok(Status::Complete(
1712    //             RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS.len()
1713    //         ))
1714    //     );
1715    //     assert_eq!(response.version.unwrap(), 1);
1716    //     assert_eq!(response.code.unwrap(), 200);
1717    //     assert_eq!(response.reason.unwrap(), "OK");
1718    //     assert_eq!(response.headers.len(), 0);
1719    // }
1720
1721    // /// This is technically allowed by the spec, but we only support multiple spaces as an option,
1722    // /// not stray `\r`s.
1723    // static RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] = b"HTTP/1.1 200\rOK\r\n\r\n";
1724
1725    // #[test]
1726    // fn test_forbid_response_with_weird_whitespace_delimiters() {
1727    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1728    //     let mut response = Response::new(&mut headers[..]);
1729    //     let result = response.parse(RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
1730
1731    //     assert_eq!(result, Err(crate::Error::Status));
1732    // }
1733
1734    // #[test]
1735    // fn test_still_forbid_response_with_weird_whitespace_delimiters() {
1736    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1737    //     let mut response = Response::new(&mut headers[..]);
1738    //     let result = crate::ParserConfig::default()
1739    //         .allow_multiple_spaces_in_response_status_delimiters(true)
1740    //         .parse_response(&mut response, RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
1741    //     assert_eq!(result, Err(crate::Error::Status));
1742    // }
1743
1744    // static REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] = b"GET  /    HTTP/1.1\r\n\r\n";
1745
1746    // #[test]
1747    // fn test_forbid_request_with_multiple_space_delimiters() {
1748    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1749    //     let mut request = Request::new(&mut headers[..]);
1750    //     let result = request.parse(REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
1751
1752    //     assert_eq!(result, Err(crate::Error::Token));
1753    // }
1754
1755    // #[test]
1756    // fn test_allow_request_with_multiple_space_delimiters() {
1757    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1758    //     let mut request = Request::new(&mut headers[..]);
1759    //     let result = crate::ParserConfig::default()
1760    //         .allow_multiple_spaces_in_request_line_delimiters(true)
1761    //         .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
1762
1763    //     assert_eq!(
1764    //         result,
1765    //         Ok(Status::Complete(
1766    //             REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS.len()
1767    //         ))
1768    //     );
1769    //     assert_eq!(request.method.unwrap(), "GET");
1770    //     assert_eq!(request.path.unwrap(), "/");
1771    //     assert_eq!(request.version.unwrap(), 1);
1772    //     assert_eq!(request.headers.len(), 0);
1773    // }
1774
1775    // /// This is technically allowed by the spec, but we only support multiple spaces as an option,
1776    // /// not stray `\r`s.
1777    // static REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] = b"GET\r/\rHTTP/1.1\r\n\r\n";
1778
1779    // #[test]
1780    // fn test_forbid_request_with_weird_whitespace_delimiters() {
1781    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1782    //     let mut request = Request::new(&mut headers[..]);
1783    //     let result = request.parse(REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
1784
1785    //     assert_eq!(result, Err(crate::Error::Token));
1786    // }
1787
1788    // #[test]
1789    // fn test_still_forbid_request_with_weird_whitespace_delimiters() {
1790    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1791    //     let mut request = Request::new(&mut headers[..]);
1792    //     let result = crate::ParserConfig::default()
1793    //         .allow_multiple_spaces_in_request_line_delimiters(true)
1794    //         .parse_request(&mut request, REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
1795    //     assert_eq!(result, Err(crate::Error::Token));
1796    // }
1797
1798    // static REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH: &[u8] = b"GET   /foo ohno HTTP/1.1\r\n\r\n";
1799
1800    // #[test]
1801    // fn test_request_with_multiple_spaces_and_bad_path() {
1802    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1803    //     let mut request = Request::new(&mut headers[..]);
1804    //     let result = crate::ParserConfig::default()
1805    //         .allow_multiple_spaces_in_request_line_delimiters(true)
1806    //         .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH);
1807    //     assert_eq!(result, Err(crate::Error::Version));
1808    // }
1809
1810    // // This test ensure there is an error when there is a DEL character in the path
1811    // // since we allow all char from 0x21 code except DEL, this test ensure that DEL
1812    // // is not allowed in the path
1813    // static REQUEST_WITH_DEL_IN_PATH: &[u8] = b"GET   /foo\x7Fohno HTTP/1.1\r\n\r\n";
1814
1815    // #[test]
1816    // fn test_request_with_del_in_path() {
1817    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1818    //     let mut request = Request::new(&mut headers[..]);
1819    //     let result = crate::ParserConfig::default()
1820    //         .allow_multiple_spaces_in_request_line_delimiters(true)
1821    //         .parse_request(&mut request, crate::tests::REQUEST_WITH_DEL_IN_PATH);
1822    //     assert_eq!(result, Err(crate::Error::Token));
1823    // }
1824
1825    // #[test]
1826    // #[cfg_attr(miri, ignore)] // Miri is too slow for this test
1827    // fn test_all_utf8_char_in_paths() {
1828    //     // two code points
1829    //     for i in 128..256 {
1830    //         for j in 128..256 {
1831    //             let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1832    //             let mut request = Request::new(&mut headers[..]);
1833    //             let bytes = [i as u8, j as u8];
1834
1835    //             match core::str::from_utf8(&bytes) {
1836    //                 Ok(s) => {
1837    //                     let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
1838    //                     let result = crate::ParserConfig::default()
1839    //                         .allow_multiple_spaces_in_request_line_delimiters(true)
1840    //                         .parse_request(&mut request, first_line.as_bytes());
1841
1842    //                     assert_eq!(
1843    //                         result,
1844    //                         Ok(Status::Complete(20)),
1845    //                         "failed for utf8 char i: {}, j: {}",
1846    //                         i,
1847    //                         j
1848    //                     );
1849    //                 }
1850    //                 Err(_) => {
1851    //                     let mut first_line = b"GET /".to_vec();
1852    //                     first_line.extend(&bytes);
1853    //                     first_line.extend(b" HTTP/1.1\r\n\r\n");
1854
1855    //                     let result = crate::ParserConfig::default()
1856    //                         .allow_multiple_spaces_in_request_line_delimiters(true)
1857    //                         .parse_request(&mut request, first_line.as_slice());
1858
1859    //                     assert_eq!(
1860    //                         result,
1861    //                         Err(crate::Error::Token),
1862    //                         "failed for utf8 char i: {}, j: {}",
1863    //                         i,
1864    //                         j
1865    //                     );
1866    //                 }
1867    //             };
1868
1869    //             // three code points starting from 0xe0
1870    //             if i < 0xe0 {
1871    //                 continue;
1872    //             }
1873
1874    //             for k in 128..256 {
1875    //                 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1876    //                 let mut request = Request::new(&mut headers[..]);
1877    //                 let bytes = [i as u8, j as u8, k as u8];
1878
1879    //                 match core::str::from_utf8(&bytes) {
1880    //                     Ok(s) => {
1881    //                         let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
1882    //                         let result = crate::ParserConfig::default()
1883    //                             .allow_multiple_spaces_in_request_line_delimiters(true)
1884    //                             .parse_request(&mut request, first_line.as_bytes());
1885
1886    //                         assert_eq!(
1887    //                             result,
1888    //                             Ok(Status::Complete(21)),
1889    //                             "failed for utf8 char i: {}, j: {}, k: {}",
1890    //                             i,
1891    //                             j,
1892    //                             k
1893    //                         );
1894    //                     }
1895    //                     Err(_) => {
1896    //                         let mut first_line = b"GET /".to_vec();
1897    //                         first_line.extend(&bytes);
1898    //                         first_line.extend(b" HTTP/1.1\r\n\r\n");
1899
1900    //                         let result = crate::ParserConfig::default()
1901    //                             .allow_multiple_spaces_in_request_line_delimiters(true)
1902    //                             .parse_request(&mut request, first_line.as_slice());
1903
1904    //                         assert_eq!(
1905    //                             result,
1906    //                             Err(crate::Error::Token),
1907    //                             "failed for utf8 char i: {}, j: {}, k: {}",
1908    //                             i,
1909    //                             j,
1910    //                             k
1911    //                         );
1912    //                     }
1913    //                 };
1914
1915    //                 // four code points starting from 0xf0
1916    //                 if i < 0xf0 {
1917    //                     continue;
1918    //                 }
1919
1920    //                 for l in 128..256 {
1921    //                     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1922    //                     let mut request = Request::new(&mut headers[..]);
1923    //                     let bytes = [i as u8, j as u8, k as u8, l as u8];
1924
1925    //                     match core::str::from_utf8(&bytes) {
1926    //                         Ok(s) => {
1927    //                             let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
1928    //                             let result = crate::ParserConfig::default()
1929    //                                 .allow_multiple_spaces_in_request_line_delimiters(true)
1930    //                                 .parse_request(&mut request, first_line.as_bytes());
1931
1932    //                             assert_eq!(
1933    //                                 result,
1934    //                                 Ok(Status::Complete(22)),
1935    //                                 "failed for utf8 char i: {}, j: {}, k: {}, l: {}",
1936    //                                 i,
1937    //                                 j,
1938    //                                 k,
1939    //                                 l
1940    //                             );
1941    //                         }
1942    //                         Err(_) => {
1943    //                             let mut first_line = b"GET /".to_vec();
1944    //                             first_line.extend(&bytes);
1945    //                             first_line.extend(b" HTTP/1.1\r\n\r\n");
1946
1947    //                             let result = crate::ParserConfig::default()
1948    //                                 .allow_multiple_spaces_in_request_line_delimiters(true)
1949    //                                 .parse_request(&mut request, first_line.as_slice());
1950
1951    //                             assert_eq!(
1952    //                                 result,
1953    //                                 Err(crate::Error::Token),
1954    //                                 "failed for utf8 char i: {}, j: {}, k: {}, l: {}",
1955    //                                 i,
1956    //                                 j,
1957    //                                 k,
1958    //                                 l
1959    //                             );
1960    //                         }
1961    //                     };
1962    //                 }
1963    //             }
1964    //         }
1965    //     }
1966    // }
1967
1968    // static RESPONSE_WITH_SPACES_IN_CODE: &[u8] = b"HTTP/1.1 99 200 OK\r\n\r\n";
1969
1970    // #[test]
1971    // fn test_response_with_spaces_in_code() {
1972    //     let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1973    //     let mut response = Response::new(&mut headers[..]);
1974    //     let result = crate::ParserConfig::default()
1975    //         .allow_multiple_spaces_in_response_status_delimiters(true)
1976    //         .parse_response(&mut response, RESPONSE_WITH_SPACES_IN_CODE);
1977    //     assert_eq!(result, Err(crate::Error::Status));
1978    // }
1979
1980    // #[test]
1981    // fn test_response_with_empty_header_name() {
1982    //     const RESPONSE: &[u8] = b"HTTP/1.1 200 OK\r\n: hello\r\nBread: baguette\r\n\r\n";
1983
1984    //     let mut headers = [EMPTY_HEADER; 2];
1985    //     let mut response = Response::new(&mut headers[..]);
1986
1987    //     let result = crate::ParserConfig::default()
1988    //         .allow_spaces_after_header_name_in_responses(true)
1989    //         .parse_response(&mut response, RESPONSE);
1990    //     assert_eq!(result, Err(crate::Error::HeaderName));
1991
1992    //     let result = crate::ParserConfig::default()
1993    //         .ignore_invalid_headers_in_responses(true)
1994    //         .parse_response(&mut response, RESPONSE);
1995    //     assert_eq!(result, Ok(Status::Complete(45)));
1996
1997    //     assert_eq!(response.version.unwrap(), 1);
1998    //     assert_eq!(response.code.unwrap(), 200);
1999    //     assert_eq!(response.reason.unwrap(), "OK");
2000    //     assert_eq!(response.headers.len(), 1);
2001    //     assert_eq!(response.headers[0].0, "Bread");
2002    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2003    // }
2004
2005    // #[test]
2006    // fn test_request_with_empty_header_name() {
2007    //     const RESPONSE: &[u8] = b"GET / HTTP/1.1\r\n: hello\r\nBread: baguette\r\n\r\n";
2008
2009    //     let mut headers = [EMPTY_HEADER; 2];
2010    //     let mut request = Request::new(&mut headers[..]);
2011
2012    //     let result = crate::ParserConfig::default().parse_request(&mut request, RESPONSE);
2013    //     assert_eq!(result, Err(crate::Error::HeaderName));
2014
2015    //     let result = crate::ParserConfig::default()
2016    //         .ignore_invalid_headers_in_requests(true)
2017    //         .parse_request(&mut request, RESPONSE);
2018    //     assert_eq!(result, Ok(Status::Complete(44)));
2019    // }
2020
2021    // #[test]
2022    // fn test_request_with_whitespace_between_header_name_and_colon() {
2023    //     const REQUEST: &[u8] =
2024    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials  : true\r\nBread: baguette\r\n\r\n";
2025
2026    //     let mut headers = [EMPTY_HEADER; 2];
2027    //     let mut request = Request::new(&mut headers[..]);
2028
2029    //     let result = crate::ParserConfig::default()
2030    //         .allow_spaces_after_header_name_in_responses(true)
2031    //         .parse_request(&mut request, REQUEST);
2032    //     assert_eq!(result, Err(crate::Error::HeaderName));
2033
2034    //     let result = crate::ParserConfig::default()
2035    //         .ignore_invalid_headers_in_responses(true)
2036    //         .parse_request(&mut request, REQUEST);
2037    //     assert_eq!(result, Err(crate::Error::HeaderName));
2038    // }
2039
2040    // #[test]
2041    // fn test_response_with_invalid_char_between_header_name_and_colon() {
2042    //     const RESPONSE: &[u8] =
2043    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\xFF  : true\r\nBread: baguette\r\n\r\n";
2044
2045    //     let mut headers = [EMPTY_HEADER; 2];
2046    //     let mut response = Response::new(&mut headers[..]);
2047
2048    //     let result = crate::ParserConfig::default()
2049    //         .allow_spaces_after_header_name_in_responses(true)
2050    //         .parse_response(&mut response, RESPONSE);
2051    //     assert_eq!(result, Err(crate::Error::HeaderName));
2052
2053    //     let result = crate::ParserConfig::default()
2054    //         .ignore_invalid_headers_in_responses(true)
2055    //         .parse_response(&mut response, RESPONSE);
2056
2057    //     assert_eq!(result, Ok(Status::Complete(79)));
2058    //     assert_eq!(response.version.unwrap(), 1);
2059    //     assert_eq!(response.code.unwrap(), 200);
2060    //     assert_eq!(response.reason.unwrap(), "OK");
2061    //     assert_eq!(response.headers.len(), 1);
2062    //     assert_eq!(response.headers[0].0, "Bread");
2063    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2064    // }
2065
2066    // #[test]
2067    // fn test_request_with_invalid_char_between_header_name_and_colon() {
2068    //     const REQUEST: &[u8] =
2069    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\xFF  : true\r\nBread: baguette\r\n\r\n";
2070
2071    //     let mut headers = [EMPTY_HEADER; 2];
2072    //     let mut request = Request::new(&mut headers[..]);
2073
2074    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2075    //     assert_eq!(result, Err(crate::Error::HeaderName));
2076
2077    //     let result = crate::ParserConfig::default()
2078    //         .ignore_invalid_headers_in_requests(true)
2079    //         .parse_request(&mut request, REQUEST);
2080    //     assert_eq!(result, Ok(Status::Complete(78)));
2081    // }
2082
2083    // #[test]
2084    // fn test_ignore_header_line_with_missing_colon_in_response() {
2085    //     const RESPONSE: &[u8] =
2086    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
2087
2088    //     let mut headers = [EMPTY_HEADER; 2];
2089    //     let mut response = Response::new(&mut headers[..]);
2090
2091    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2092    //     assert_eq!(result, Err(crate::Error::HeaderName));
2093
2094    //     let result = crate::ParserConfig::default()
2095    //         .ignore_invalid_headers_in_responses(true)
2096    //         .parse_response(&mut response, RESPONSE);
2097    //     assert_eq!(result, Ok(Status::Complete(70)));
2098
2099    //     assert_eq!(response.version.unwrap(), 1);
2100    //     assert_eq!(response.code.unwrap(), 200);
2101    //     assert_eq!(response.reason.unwrap(), "OK");
2102    //     assert_eq!(response.headers.len(), 1);
2103    //     assert_eq!(response.headers[0].0, "Bread");
2104    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2105    // }
2106
2107    // #[test]
2108    // fn test_ignore_header_line_with_missing_colon_in_request() {
2109    //     const REQUEST: &[u8] =
2110    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
2111
2112    //     let mut headers = [EMPTY_HEADER; 2];
2113    //     let mut request = Request::new(&mut headers[..]);
2114
2115    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2116    //     assert_eq!(result, Err(crate::Error::HeaderName));
2117
2118    //     let result = crate::ParserConfig::default()
2119    //         .ignore_invalid_headers_in_requests(true)
2120    //         .parse_request(&mut request, REQUEST);
2121    //     assert_eq!(result, Ok(Status::Complete(69)));
2122    // }
2123
2124    // #[test]
2125    // fn test_response_header_with_missing_colon_with_folding() {
2126    //     const RESPONSE: &[u8] =
2127    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials   \r\n hello\r\nBread: baguette\r\n\r\n";
2128
2129    //     let mut headers = [EMPTY_HEADER; 2];
2130    //     let mut response = Response::new(&mut headers[..]);
2131
2132    //     let result = crate::ParserConfig::default()
2133    //         .allow_obsolete_multiline_headers_in_responses(true)
2134    //         .allow_spaces_after_header_name_in_responses(true)
2135    //         .parse_response(&mut response, RESPONSE);
2136    //     assert_eq!(result, Err(crate::Error::HeaderName));
2137
2138    //     let result = crate::ParserConfig::default()
2139    //         .ignore_invalid_headers_in_responses(true)
2140    //         .parse_response(&mut response, RESPONSE);
2141    //     assert_eq!(result, Ok(Status::Complete(81)));
2142
2143    //     assert_eq!(response.version.unwrap(), 1);
2144    //     assert_eq!(response.code.unwrap(), 200);
2145    //     assert_eq!(response.reason.unwrap(), "OK");
2146    //     assert_eq!(response.headers.len(), 1);
2147    //     assert_eq!(response.headers[0].0, "Bread");
2148    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2149    // }
2150
2151    // #[test]
2152    // fn test_request_header_with_missing_colon_with_folding() {
2153    //     const REQUEST: &[u8] =
2154    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials   \r\n hello\r\nBread: baguette\r\n\r\n";
2155
2156    //     let mut headers = [EMPTY_HEADER; 2];
2157    //     let mut request = Request::new(&mut headers[..]);
2158
2159    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2160    //     assert_eq!(result, Err(crate::Error::HeaderName));
2161
2162    //     let result = crate::ParserConfig::default()
2163    //         .ignore_invalid_headers_in_requests(true)
2164    //         .parse_request(&mut request, REQUEST);
2165    //     assert_eq!(result, Ok(Status::Complete(80)));
2166    // }
2167
2168    // #[test]
2169    // fn test_response_header_with_nul_in_header_name() {
2170    //     const RESPONSE: &[u8] =
2171    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
2172
2173    //     let mut headers = [EMPTY_HEADER; 2];
2174    //     let mut response = Response::new(&mut headers[..]);
2175
2176    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2177    //     assert_eq!(result, Err(crate::Error::HeaderName));
2178
2179    //     let result = crate::ParserConfig::default()
2180    //         .ignore_invalid_headers_in_responses(true)
2181    //         .parse_response(&mut response, RESPONSE);
2182    //     assert_eq!(result, Err(crate::Error::HeaderName));
2183    // }
2184
2185    // #[test]
2186    // fn test_request_header_with_nul_in_header_name() {
2187    //     const REQUEST: &[u8] =
2188    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
2189
2190    //     let mut headers = [EMPTY_HEADER; 2];
2191    //     let mut request = Request::new(&mut headers[..]);
2192
2193    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2194    //     assert_eq!(result, Err(crate::Error::HeaderName));
2195
2196    //     let result = crate::ParserConfig::default()
2197    //         .ignore_invalid_headers_in_requests(true)
2198    //         .parse_request(&mut request, REQUEST);
2199    //     assert_eq!(result, Err(crate::Error::HeaderName));
2200    // }
2201
2202    // #[test]
2203    // fn test_header_with_cr_in_header_name() {
2204    //     const RESPONSE: &[u8] =
2205    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
2206
2207    //     let mut headers = [EMPTY_HEADER; 2];
2208    //     let mut response = Response::new(&mut headers[..]);
2209
2210    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2211    //     assert_eq!(result, Err(crate::Error::HeaderName));
2212
2213    //     let result = crate::ParserConfig::default()
2214    //         .ignore_invalid_headers_in_responses(true)
2215    //         .parse_response(&mut response, RESPONSE);
2216    //     assert_eq!(result, Err(crate::Error::HeaderName));
2217
2218    //     const REQUEST: &[u8] =
2219    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
2220
2221    //     let mut headers = [EMPTY_HEADER; 2];
2222    //     let mut request = Request::new(&mut headers[..]);
2223
2224    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2225    //     assert_eq!(result, Err(crate::Error::HeaderName));
2226
2227    //     let result = crate::ParserConfig::default()
2228    //         .ignore_invalid_headers_in_requests(true)
2229    //         .parse_request(&mut request, REQUEST);
2230    //     assert_eq!(result, Err(crate::Error::HeaderName));
2231    // }
2232
2233    // #[test]
2234    // fn test_header_with_nul_in_whitespace_before_colon() {
2235    //     const RESPONSE: &[u8] =
2236    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials   \0: hello\r\nBread: baguette\r\n\r\n";
2237
2238    //     let mut headers = [EMPTY_HEADER; 2];
2239    //     let mut response = Response::new(&mut headers[..]);
2240
2241    //     let result = crate::ParserConfig::default()
2242    //         .allow_spaces_after_header_name_in_responses(true)
2243    //         .parse_response(&mut response, RESPONSE);
2244    //     assert_eq!(result, Err(crate::Error::HeaderName));
2245
2246    //     let result = crate::ParserConfig::default()
2247    //         .allow_spaces_after_header_name_in_responses(true)
2248    //         .ignore_invalid_headers_in_responses(true)
2249    //         .parse_response(&mut response, RESPONSE);
2250    //     assert_eq!(result, Err(crate::Error::HeaderName));
2251
2252    //     const REQUEST: &[u8] =
2253    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials   \0: hello\r\nBread: baguette\r\n\r\n";
2254
2255    //     let mut headers = [EMPTY_HEADER; 2];
2256    //     let mut request = Request::new(&mut headers[..]);
2257
2258    //     let result = crate::ParserConfig::default()
2259    //         .ignore_invalid_headers_in_requests(true)
2260    //         .parse_request(&mut request, REQUEST);
2261    //     assert_eq!(result, Err(crate::Error::HeaderName));
2262    // }
2263
2264    // #[test]
2265    // fn test_header_with_nul_in_value() {
2266    //     const RESPONSE: &[u8] =
2267    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
2268
2269    //     let mut headers = [EMPTY_HEADER; 2];
2270    //     let mut response = Response::new(&mut headers[..]);
2271
2272    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2273    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2274
2275    //     let result = crate::ParserConfig::default()
2276    //         .ignore_invalid_headers_in_responses(true)
2277    //         .parse_response(&mut response, RESPONSE);
2278    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2279
2280    //     const REQUEST: &[u8] =
2281    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
2282
2283    //     let mut headers = [EMPTY_HEADER; 2];
2284    //     let mut request = Request::new(&mut headers[..]);
2285
2286    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2287    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2288
2289    //     let result = crate::ParserConfig::default()
2290    //         .ignore_invalid_headers_in_requests(true)
2291    //         .parse_request(&mut request, REQUEST);
2292    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2293    // }
2294
2295    // #[test]
2296    // fn test_header_with_invalid_char_in_value() {
2297    //     const RESPONSE: &[u8] =
2298    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
2299
2300    //     let mut headers = [EMPTY_HEADER; 2];
2301    //     let mut response = Response::new(&mut headers[..]);
2302
2303    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2304    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2305
2306    //     let result = crate::ParserConfig::default()
2307    //         .ignore_invalid_headers_in_responses(true)
2308    //         .parse_response(&mut response, RESPONSE);
2309    //     assert_eq!(result, Ok(Status::Complete(78)));
2310
2311    //     assert_eq!(response.version.unwrap(), 1);
2312    //     assert_eq!(response.code.unwrap(), 200);
2313    //     assert_eq!(response.reason.unwrap(), "OK");
2314    //     assert_eq!(response.headers.len(), 1);
2315    //     assert_eq!(response.headers[0].0, "Bread");
2316    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2317
2318    //     const REQUEST: &[u8] =
2319    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
2320
2321    //     let mut headers = [EMPTY_HEADER; 2];
2322    //     let mut request = Request::new(&mut headers[..]);
2323
2324    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2325    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2326
2327    //     let result = crate::ParserConfig::default()
2328    //         .ignore_invalid_headers_in_requests(true)
2329    //         .parse_request(&mut request, REQUEST);
2330    //     assert_eq!(result, Ok(Status::Complete(77)));
2331
2332    //     assert_eq!(request.version.unwrap(), 1);
2333    //     assert_eq!(request.method.unwrap(), "GET");
2334    //     assert_eq!(request.path.unwrap(), "/");
2335    //     assert_eq!(request.headers.len(), 1);
2336    //     assert_eq!(request.headers[0].0, "Bread");
2337    //     assert_eq!(request.headers[0].1, &b"baguette"[..]);
2338    // }
2339
2340    // #[test]
2341    // fn test_header_with_invalid_char_in_value_with_folding() {
2342    //     const RESPONSE: &[u8] =
2343    //         b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o  \n world!\r\nBread: baguette\r\n\r\n";
2344
2345    //     let mut headers = [EMPTY_HEADER; 2];
2346    //     let mut response = Response::new(&mut headers[..]);
2347
2348    //     let result = crate::ParserConfig::default().parse_response(&mut response, RESPONSE);
2349    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2350
2351    //     let result = crate::ParserConfig::default()
2352    //         .ignore_invalid_headers_in_responses(true)
2353    //         .parse_response(&mut response, RESPONSE);
2354    //     assert_eq!(result, Ok(Status::Complete(88)));
2355
2356    //     assert_eq!(response.version.unwrap(), 1);
2357    //     assert_eq!(response.code.unwrap(), 200);
2358    //     assert_eq!(response.reason.unwrap(), "OK");
2359    //     assert_eq!(response.headers.len(), 1);
2360    //     assert_eq!(response.headers[0].0, "Bread");
2361    //     assert_eq!(response.headers[0].1, &b"baguette"[..]);
2362
2363    //     const REQUEST: &[u8] =
2364    //         b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o  \n world!\r\nBread: baguette\r\n\r\n";
2365
2366    //     let mut headers = [EMPTY_HEADER; 2];
2367    //     let mut request = Request::new(&mut headers[..]);
2368
2369    //     let result = crate::ParserConfig::default().parse_request(&mut request, REQUEST);
2370    //     assert_eq!(result, Err(crate::Error::HeaderValue));
2371
2372    //     let result = crate::ParserConfig::default()
2373    //         .ignore_invalid_headers_in_requests(true)
2374    //         .parse_request(&mut request, REQUEST);
2375    //     assert_eq!(result, Ok(Status::Complete(87)));
2376
2377    //     assert_eq!(request.version.unwrap(), 1);
2378    //     assert_eq!(request.method.unwrap(), "GET");
2379    //     assert_eq!(request.path.unwrap(), "/");
2380    //     assert_eq!(request.headers.len(), 1);
2381    //     assert_eq!(request.headers[0].0, "Bread");
2382    //     assert_eq!(request.headers[0].1, &b"baguette"[..]);
2383    // }
2384
2385    // #[test]
2386    // fn test_method_within_buffer() {
2387    //     const REQUEST: &[u8] = b"GET / HTTP/1.1\r\n\r\n";
2388
2389    //     let mut headers = [EMPTY_HEADER; 0];
2390    //     let mut request = Request::new(&mut headers[..]);
2391
2392    //     crate::ParserConfig::default()
2393    //         .parse_request(&mut request, REQUEST)
2394    //         .unwrap();
2395
2396    //     // SAFETY: will not wrap
2397    //     let buf_end = unsafe { REQUEST.as_ptr().add(REQUEST.len()) };
2398    //     // Check that the method str is within the buffer
2399    //     let method = request.method.unwrap();
2400    //     assert!(REQUEST.as_ptr() <= method.as_ptr());
2401    //     assert!(method.as_ptr() <= buf_end);
2402    // }
2403
2404    // static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER: &[u8] =
2405    //     b"HTTP/1.1 200 OK\r\n Space-Before-Header: hello there\r\n\r\n";
2406
2407    // #[test]
2408    // fn test_forbid_response_with_space_before_first_header() {
2409    //     let mut headers = [EMPTY_HEADER; 1];
2410    //     let mut response = Response::new(&mut headers[..]);
2411    //     let result = response.parse(RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
2412
2413    //     assert_eq!(result, Err(crate::Error::HeaderName));
2414    // }
2415
2416    // #[test]
2417    // fn test_allow_response_response_with_space_before_first_header() {
2418    //     let mut headers = [EMPTY_HEADER; 1];
2419    //     let mut response = Response::new(&mut headers[..]);
2420    //     let result = crate::ParserConfig::default()
2421    //         .allow_space_before_first_header_name(true)
2422    //         .parse_response(&mut response, RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
2423
2424    //     assert_eq!(
2425    //         result,
2426    //         Ok(Status::Complete(
2427    //             RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER.len()
2428    //         ))
2429    //     );
2430    //     assert_eq!(response.version.unwrap(), 1);
2431    //     assert_eq!(response.code.unwrap(), 200);
2432    //     assert_eq!(response.reason.unwrap(), "OK");
2433    //     assert_eq!(response.headers.len(), 1);
2434    //     assert_eq!(response.headers[0].0, "Space-Before-Header");
2435    //     assert_eq!(response.headers[0].1, &b"hello there"[..]);
2436    // }
2437
2438    // #[test]
2439    // fn test_no_space_after_colon() {
2440    //     let mut headers = [EMPTY_HEADER; 1];
2441    //     let mut response = Response::new(&mut headers[..]);
2442    //     let result = crate::ParserConfig::default()
2443    //         .parse_response(&mut response, b"HTTP/1.1 200 OK\r\nfoo:bar\r\n\r\n");
2444
2445    //     assert_eq!(result, Ok(Status::Complete(28)));
2446    //     assert_eq!(response.version.unwrap(), 1);
2447    //     assert_eq!(response.code.unwrap(), 200);
2448    //     assert_eq!(response.reason.unwrap(), "OK");
2449    //     assert_eq!(response.headers.len(), 1);
2450    //     assert_eq!(response.headers[0].0, "foo");
2451    //     assert_eq!(response.headers[0].1, &b"bar"[..]);
2452    // }
2453
2454    // #[test]
2455    // fn test_request_with_leading_space() {
2456    //     let mut headers = [EMPTY_HEADER; 1];
2457    //     let mut request = Request::new(&mut headers[..]);
2458    //     let result = crate::ParserConfig::default()
2459    //         .parse_request(&mut request, b" GET / HTTP/1.1\r\nfoo:bar\r\n\r\n");
2460
2461    //     assert_eq!(result, Err(Error::Token));
2462    // }
2463
2464    // #[test]
2465    // fn test_request_with_invalid_method() {
2466    //     let mut headers = [EMPTY_HEADER; 1];
2467    //     let mut request = Request::new(&mut headers[..]);
2468    //     let result = crate::ParserConfig::default()
2469    //         .parse_request(&mut request, b"P()ST / HTTP/1.1\r\nfoo:bar\r\n\r\n");
2470
2471    //     assert_eq!(result, Err(Error::Token));
2472    // }
2473
2474    // #[test]
2475    // fn test_utf8_in_path_ok() {
2476    //     let mut headers = [EMPTY_HEADER; 1];
2477    //     let mut request = Request::new(&mut headers[..]);
2478
2479    //     let result = crate::ParserConfig::default().parse_request(
2480    //         &mut request,
2481    //         b"GET /test?post=I\xE2\x80\x99msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n",
2482    //     );
2483
2484    //     assert_eq!(result, Ok(Status::Complete(67)));
2485    //     assert_eq!(request.version.unwrap(), 1);
2486    //     assert_eq!(request.method.unwrap(), "GET");
2487    //     assert_eq!(request.path.unwrap(), "/test?post=I’msorryIforkedyou");
2488    //     assert_eq!(request.headers.len(), 1);
2489    //     assert_eq!(request.headers[0].0, "Host");
2490    //     assert_eq!(request.headers[0].1, &b"example.org"[..]);
2491    // }
2492
2493    // #[test]
2494    // fn test_bad_utf8_in_path() {
2495    //     let mut headers = [EMPTY_HEADER; 1];
2496    //     let mut request = Request::new(&mut headers[..]);
2497
2498    //     let result = crate::ParserConfig::default().parse_request(
2499    //         &mut request,
2500    //         b"GET /test?post=I\xE2msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n",
2501    //     );
2502
2503    //     assert_eq!(result, Err(crate::Error::Token));
2504    // }
2505}