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
9use 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)]
38pub 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#[inline]
58fn is_token(b: u8) -> bool {
59 b > 0x1F && b < 0x7F
60}
61
62static URI_MAP: [bool; 256] = byte_map![
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
690, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
711, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
731, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
751, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
771, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
791, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
810, 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#[derive(Copy, Clone, PartialEq, Eq, Debug)]
149pub enum Error {
150 HeaderName,
152 HeaderValue,
154 NewLine,
156 Status,
158 Token,
160 TooManyHeaders,
162 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#[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
205pub type Result<T> = result::Result<Status<T>, Error>;
211
212#[derive(Copy, Clone, Eq, PartialEq, Debug)]
218pub enum Status<T> {
219 Complete(T),
221 Partial
223}
224
225impl<T> Status<T> {
226 #[inline]
228 pub fn is_complete(&self) -> bool {
229 match *self {
230 Status::Complete(..) => true,
231 Status::Partial => false
232 }
233 }
234
235 #[inline]
237 pub fn is_partial(&self) -> bool {
238 match *self {
239 Status::Complete(..) => false,
240 Status::Partial => true
241 }
242 }
243
244 #[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#[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 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 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 pub fn multiple_spaces_in_request_line_delimiters_are_allowed(&self) -> bool {
297 self.allow_multiple_spaces_in_request_line_delimiters
298 }
299
300 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 pub fn multiple_spaces_in_response_status_delimiters_are_allowed(&self) -> bool {
321 self.allow_multiple_spaces_in_response_status_delimiters
322 }
323
324 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 pub fn obsolete_multiline_headers_in_responses_are_allowed(&self) -> bool {
357 self.allow_obsolete_multiline_headers_in_responses
358 }
359
360 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 pub fn space_before_first_header_name_are_allowed(&self) -> bool {
390 self.allow_space_before_first_header_name
391 }
392
393 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 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 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 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 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 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#[derive(Debug, Eq, PartialEq)]
505pub struct Request<'headers, 'buf> {
506 pub method: Option<&'buf str>,
508 pub path: Option<&'buf str>,
510 pub version: Option<u8>,
512 pub headers: &'headers mut [Header<'buf>]
514}
515
516impl<'h, 'b> Request<'h, 'b> {
517 #[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 self.headers = unsafe { assume_init_slice(headers) };
562
563 Ok(Status::Complete(len + headers_len))
564 }
565
566 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 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 self.headers = &mut *(headers as *mut [Header<'_>]);
590 other
591 },
592 }
593 }
594 }
595
596 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 unsafe { bytes.bump() };
612 expect!(bytes.next() == b'\n' => Err(Error::NewLine));
613 }
614 Some(b'\n') => {
615 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 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#[derive(Debug, Eq, PartialEq)]
651pub struct Response<'headers, 'buf> {
652 pub version: Option<u8>,
654 pub code: Option<u16>,
656 pub reason: Option<&'buf str>,
660 pub headers: &'headers mut [Header<'buf>]
662}
663
664impl<'h, 'b> Response<'h, 'b> {
665 #[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 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 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 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 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 self.headers = unsafe { assume_init_slice(headers) };
760 Ok(Status::Complete(len + headers_len))
761 }
762}
763
764#[derive(Copy, Clone, Eq, PartialEq)]
766pub struct Header<'a> {
767 pub name: &'a str,
771 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
791pub const EMPTY_HEADER: Header<'static> = Header { name: "", value: b"" };
800
801#[inline]
802#[doc(hidden)]
803#[allow(missing_docs)]
804pub fn parse_version(bytes: &mut Bytes) -> Result<u8> {
806 if let Some(eight) = bytes.peek_n::<[u8; 8]>(8) {
807 let h10: u64 = u64::from_ne_bytes(*b"HTTP/1.0");
809 let h11: u64 = u64::from_ne_bytes(*b"HTTP/1.1");
810 unsafe {
812 bytes.advance(8);
813 }
814 let block = u64::from_ne_bytes(eight);
815 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 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)]
842pub 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 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 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#[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 unsafe {
896 let bytes = bytes.slice_skip(2);
897 if !seen_obs_text {
898 str::from_utf8_unchecked(bytes)
900 } else {
901 ""
903 }
904 },
905 ));
906 } else if b == b'\n' {
907 return Ok(Status::Complete(
908 unsafe {
912 let bytes = bytes.slice_skip(1);
913 if !seen_obs_text {
914 str::from_utf8_unchecked(bytes)
916 } else {
917 ""
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 return Err(Error::Token);
936 }
937
938 loop {
939 let b = next!(bytes);
940 if b == b' ' {
941 return Ok(Status::Complete(
942 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)]
954pub 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 if end == start {
963 return Err(Error::Token);
964 }
965
966 return Ok(Status::Complete(
967 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
986pub 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 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
1046fn 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 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 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 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 return Ok(Status::Partial);
1100 }
1101 Some(b' ') | Some(b'\t') => {
1102 continue $label;
1104 }
1105 _ => {
1106 },
1111 }
1112 }
1113 }
1114 }
1115
1116 'headers: loop {
1117 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 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 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 let header_name: &str = 'name: loop {
1184 simd::match_header_name_vectored(bytes);
1185 let mut b = next!(bytes);
1186
1187 let bslice = unsafe { bytes.slice_skip(1) };
1189 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 '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 break 'value &whitespace_slice[0..0];
1239 }
1240
1241 'value_lines: loop {
1242 simd::match_header_value_vectored(bytes);
1245 let b = next!(bytes);
1246
1247 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 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 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 &value_slice[0..last_visible+1]
1278 } else {
1279 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
1294pub 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 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 b';' if !in_ext => {
1362 in_ext = true;
1363 in_chunk_size = false;
1364 }
1365 b'\t' | b' ' if !in_ext && !in_chunk_size => {}
1368 b'\t' | b' ' if in_chunk_size => in_chunk_size = false,
1370 _ if in_ext => {}
1376 _ => 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_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_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_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_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 req! {
1554 test_request_one_byte_method,
1555 b"G", Ok(Status::Partial),
1556 |_req| {}
1557 }
1558
1559 req! {
1561 test_request_partial_method,
1562 b"GE", Ok(Status::Partial),
1563 |_req| {}
1564 }
1565
1566 req! {
1568 test_request_method_no_delimiter,
1569 b"GET", Ok(Status::Partial),
1570 |_req| {}
1571 }
1572
1573 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); 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 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); 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 #[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 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 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 let buf_end = unsafe { REQUEST.as_ptr().add(REQUEST.len()) };
2624 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}