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