httparse/
lib.rs

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
28use core::{fmt, result, str};
29use core::mem::MaybeUninit;
30
31use crate::iter::Bytes;
32
33mod iter;
34#[macro_use] mod macros;
35mod 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
40pub 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]
58fn 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?
65static 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]
94pub(crate) fn is_uri_token(b: u8) -> bool {
95    URI_MAP[b as usize]
96}
97
98static 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]
118pub(crate) fn is_header_name_token(b: u8) -> bool {
119    HEADER_NAME_MAP[b as usize]
120}
121
122static 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]
143pub(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)]
149pub 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
166impl Error {
167    #[inline]
168    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
181impl fmt::Display for Error {
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        f.write_str(self.description_str())
184    }
185}
186
187#[cfg(feature = "std")]
188impl std::error::Error for Error {
189    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)]
197pub struct InvalidChunkSize;
198
199impl fmt::Display for InvalidChunkSize {
200    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)`.
210pub 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)]
218pub enum Status<T> {
219    /// The completed result.
220    Complete(T),
221    /// A partial result.
222    Partial
223}
224
225impl<T> Status<T> {
226    /// Convenience method to check if status is complete.
227    #[inline]
228    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]
237    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]
247    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)]
257pub 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
267impl ParserConfig {
268    /// Sets whether spaces and tabs should be allowed after header names in responses.
269    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
290    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.
296    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
314    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.
320    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    /// ```
347    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.
356    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    /// ```
383    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
389    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.
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
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.
442    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.
451    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.
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
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)]
505pub 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
516impl<'h, 'b> Request<'h, 'b> {
517    /// Creates a new Request, using a slice of headers you allocate.
518    #[inline]
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
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`
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
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.
599    pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
600        self.parse_with_config(buf, &Default::default())
601    }
602}
603
604#[inline]
605fn 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]
630fn 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)]
651pub 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
664impl<'h, 'b> Response<'h, 'b> {
665    /// Creates a new `Response` using a slice of `Header`s you have allocated.
666    #[inline]
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`.
677    pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
678        self.parse_with_config(buf, &ParserConfig::default())
679    }
680
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
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)]
766pub 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
778impl<'a> fmt::Debug for Header<'a> {
779    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/// ```
799pub 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
805pub 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
843pub 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]
883fn 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]
931fn 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
955pub 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]
976fn 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/// ```
1004pub 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]
1014fn 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
1027unsafe 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}
1032unsafe 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)]
1039struct 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 */
1055fn 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/// ```
1306pub 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)]
1385mod 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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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}