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