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