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, mem, 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_method_token(b: u8) -> bool {
59 match b {
60 b'A'..=b'Z' => true,
62 _ => TOKEN_MAP[b as usize],
63 }
64}
65
66static URI_MAP: [bool; 256] = byte_map!(
70 b'!'..=0x7e | 0x80..=0xFF
71);
72
73#[inline]
74pub(crate) fn is_uri_token(b: u8) -> bool {
75 URI_MAP[b as usize]
76}
77
78static TOKEN_MAP: [bool; 256] = byte_map!(
79 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' |
80 b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' | b'*' | b'+' |
81 b'-' | b'.' | b'^' | b'_' | b'`' | b'|' | b'~'
82);
83
84#[inline]
85pub(crate) fn is_header_name_token(b: u8) -> bool {
86 TOKEN_MAP[b as usize]
87}
88
89
90static HEADER_VALUE_MAP: [bool; 256] = byte_map!(
91 b'\t' | b' '..=0x7e | 0x80..=0xFF
92);
93
94
95#[inline]
96pub(crate) fn is_header_value_token(b: u8) -> bool {
97 HEADER_VALUE_MAP[b as usize]
98}
99
100#[derive(Copy, Clone, PartialEq, Eq, Debug)]
102pub enum Error {
103 HeaderName,
105 HeaderValue,
107 NewLine,
109 Status,
111 Token,
113 TooManyHeaders,
115 Version,
117}
118
119impl Error {
120 #[inline]
121 fn description_str(&self) -> &'static str {
122 match *self {
123 Error::HeaderName => "invalid header name",
124 Error::HeaderValue => "invalid header value",
125 Error::NewLine => "invalid new line",
126 Error::Status => "invalid response status",
127 Error::Token => "invalid token",
128 Error::TooManyHeaders => "too many headers",
129 Error::Version => "invalid HTTP version",
130 }
131 }
132}
133
134impl fmt::Display for Error {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.write_str(self.description_str())
137 }
138}
139
140#[cfg(feature = "std")]
141impl std::error::Error for Error {
142 fn description(&self) -> &str {
143 self.description_str()
144 }
145}
146
147#[derive(Debug, PartialEq, Eq)]
150pub struct InvalidChunkSize;
151
152impl fmt::Display for InvalidChunkSize {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 f.write_str("invalid chunk size")
155 }
156}
157
158pub type Result<T> = result::Result<Status<T>, Error>;
164
165#[derive(Copy, Clone, Eq, PartialEq, Debug)]
171pub enum Status<T> {
172 Complete(T),
174 Partial
176}
177
178impl<T> Status<T> {
179 #[inline]
181 pub fn is_complete(&self) -> bool {
182 match *self {
183 Status::Complete(..) => true,
184 Status::Partial => false
185 }
186 }
187
188 #[inline]
190 pub fn is_partial(&self) -> bool {
191 match *self {
192 Status::Complete(..) => false,
193 Status::Partial => true
194 }
195 }
196
197 #[inline]
200 pub fn unwrap(self) -> T {
201 match self {
202 Status::Complete(t) => t,
203 Status::Partial => panic!("Tried to unwrap Status::Partial")
204 }
205 }
206}
207
208#[derive(Clone, Debug, Default)]
210pub struct ParserConfig {
211 allow_spaces_after_header_name_in_responses: bool,
212 allow_obsolete_multiline_headers_in_responses: bool,
213 allow_multiple_spaces_in_request_line_delimiters: bool,
214 allow_multiple_spaces_in_response_status_delimiters: bool,
215 allow_space_before_first_header_name: bool,
216 ignore_invalid_headers_in_responses: bool,
217 ignore_invalid_headers_in_requests: bool,
218}
219
220impl ParserConfig {
221 pub fn allow_spaces_after_header_name_in_responses(
223 &mut self,
224 value: bool,
225 ) -> &mut Self {
226 self.allow_spaces_after_header_name_in_responses = value;
227 self
228 }
229
230 pub fn allow_multiple_spaces_in_request_line_delimiters(&mut self, value: bool) -> &mut Self {
244 self.allow_multiple_spaces_in_request_line_delimiters = value;
245 self
246 }
247
248 pub fn multiple_spaces_in_request_line_delimiters_are_allowed(&self) -> bool {
250 self.allow_multiple_spaces_in_request_line_delimiters
251 }
252
253 pub fn allow_multiple_spaces_in_response_status_delimiters(&mut self, value: bool) -> &mut Self {
268 self.allow_multiple_spaces_in_response_status_delimiters = value;
269 self
270 }
271
272 pub fn multiple_spaces_in_response_status_delimiters_are_allowed(&self) -> bool {
274 self.allow_multiple_spaces_in_response_status_delimiters
275 }
276
277 pub fn allow_obsolete_multiline_headers_in_responses(
301 &mut self,
302 value: bool,
303 ) -> &mut Self {
304 self.allow_obsolete_multiline_headers_in_responses = value;
305 self
306 }
307
308 pub fn obsolete_multiline_headers_in_responses_are_allowed(&self) -> bool {
310 self.allow_obsolete_multiline_headers_in_responses
311 }
312
313 pub fn allow_space_before_first_header_name(&mut self, value: bool) -> &mut Self {
337 self.allow_space_before_first_header_name = value;
338 self
339 }
340
341 pub fn space_before_first_header_name_are_allowed(&self) -> bool {
343 self.allow_space_before_first_header_name
344 }
345
346 pub fn parse_request<'buf>(
348 &self,
349 request: &mut Request<'_, 'buf>,
350 buf: &'buf [u8],
351 ) -> Result<usize> {
352 request.parse_with_config(buf, self)
353 }
354
355 pub fn parse_request_with_uninit_headers<'headers, 'buf>(
357 &self,
358 request: &mut Request<'headers, 'buf>,
359 buf: &'buf [u8],
360 headers: &'headers mut [MaybeUninit<Header<'buf>>],
361 ) -> Result<usize> {
362 request.parse_with_config_and_uninit_headers(buf, self, headers)
363 }
364
365 pub fn ignore_invalid_headers_in_responses(
396 &mut self,
397 value: bool,
398 ) -> &mut Self {
399 self.ignore_invalid_headers_in_responses = value;
400 self
401 }
402
403 pub fn ignore_invalid_headers_in_requests(
405 &mut self,
406 value: bool,
407 ) -> &mut Self {
408 self.ignore_invalid_headers_in_requests = value;
409 self
410 }
411
412 pub fn parse_response<'buf>(
414 &self,
415 response: &mut Response<'_, 'buf>,
416 buf: &'buf [u8],
417 ) -> Result<usize> {
418 response.parse_with_config(buf, self)
419 }
420
421 pub fn parse_response_with_uninit_headers<'headers, 'buf>(
423 &self,
424 response: &mut Response<'headers, 'buf>,
425 buf: &'buf [u8],
426 headers: &'headers mut [MaybeUninit<Header<'buf>>],
427 ) -> Result<usize> {
428 response.parse_with_config_and_uninit_headers(buf, self, headers)
429 }
430}
431
432#[derive(Debug, Eq, PartialEq)]
458pub struct Request<'headers, 'buf> {
459 pub method: Option<&'buf str>,
461 pub path: Option<&'buf str>,
463 pub version: Option<u8>,
465 pub headers: &'headers mut [Header<'buf>]
467}
468
469impl<'h, 'b> Request<'h, 'b> {
470 #[inline]
472 pub fn new(headers: &'h mut [Header<'b>]) -> Request<'h, 'b> {
473 Request {
474 method: None,
475 path: None,
476 version: None,
477 headers,
478 }
479 }
480
481 fn parse_with_config_and_uninit_headers(
482 &mut self,
483 buf: &'b [u8],
484 config: &ParserConfig,
485 mut headers: &'h mut [MaybeUninit<Header<'b>>],
486 ) -> Result<usize> {
487 let orig_len = buf.len();
488 let mut bytes = Bytes::new(buf);
489 complete!(skip_empty_lines(&mut bytes));
490 let method = complete!(parse_method(&mut bytes));
491 self.method = Some(method);
492 if config.allow_multiple_spaces_in_request_line_delimiters {
493 complete!(skip_spaces(&mut bytes));
494 }
495 self.path = Some(complete!(parse_uri(&mut bytes)));
496 if config.allow_multiple_spaces_in_request_line_delimiters {
497 complete!(skip_spaces(&mut bytes));
498 }
499 self.version = Some(complete!(parse_version(&mut bytes)));
500 newline!(bytes);
501
502 let len = orig_len - bytes.len();
503 let headers_len = complete!(parse_headers_iter_uninit(
504 &mut headers,
505 &mut bytes,
506 &HeaderParserConfig {
507 allow_spaces_after_header_name: false,
508 allow_obsolete_multiline_headers: false,
509 allow_space_before_first_header_name: config.allow_space_before_first_header_name,
510 ignore_invalid_headers: config.ignore_invalid_headers_in_requests
511 },
512 ));
513 self.headers = unsafe { assume_init_slice(headers) };
515
516 Ok(Status::Complete(len + headers_len))
517 }
518
519 pub fn parse_with_uninit_headers(
524 &mut self,
525 buf: &'b [u8],
526 headers: &'h mut [MaybeUninit<Header<'b>>],
527 ) -> Result<usize> {
528 self.parse_with_config_and_uninit_headers(buf, &Default::default(), headers)
529 }
530
531 fn parse_with_config(&mut self, buf: &'b [u8], config: &ParserConfig) -> Result<usize> {
532 let headers = mem::take(&mut self.headers);
533
534 unsafe {
536 let headers: *mut [Header<'_>] = headers;
537 let headers = headers as *mut [MaybeUninit<Header<'_>>];
538 match self.parse_with_config_and_uninit_headers(buf, config, &mut *headers) {
539 Ok(Status::Complete(idx)) => Ok(Status::Complete(idx)),
540 other => {
541 self.headers = &mut *(headers as *mut [Header<'_>]);
543 other
544 },
545 }
546 }
547 }
548
549 pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
553 self.parse_with_config(buf, &Default::default())
554 }
555}
556
557#[inline]
558fn skip_empty_lines(bytes: &mut Bytes<'_>) -> Result<()> {
559 loop {
560 let b = bytes.peek();
561 match b {
562 Some(b'\r') => {
563 unsafe { bytes.bump() };
565 expect!(bytes.next() == b'\n' => Err(Error::NewLine));
566 }
567 Some(b'\n') => {
568 unsafe {
570 bytes.bump();
571 }
572 }
573 Some(..) => {
574 bytes.slice();
575 return Ok(Status::Complete(()));
576 }
577 None => return Ok(Status::Partial),
578 }
579 }
580}
581
582#[inline]
583fn skip_spaces(bytes: &mut Bytes<'_>) -> Result<()> {
584 loop {
585 let b = bytes.peek();
586 match b {
587 Some(b' ') => {
588 unsafe { bytes.bump() };
590 }
591 Some(..) => {
592 bytes.slice();
593 return Ok(Status::Complete(()));
594 }
595 None => return Ok(Status::Partial),
596 }
597 }
598}
599
600#[derive(Debug, Eq, PartialEq)]
604pub struct Response<'headers, 'buf> {
605 pub version: Option<u8>,
607 pub code: Option<u16>,
609 pub reason: Option<&'buf str>,
613 pub headers: &'headers mut [Header<'buf>]
615}
616
617impl<'h, 'b> Response<'h, 'b> {
618 #[inline]
620 pub fn new(headers: &'h mut [Header<'b>]) -> Response<'h, 'b> {
621 Response {
622 version: None,
623 code: None,
624 reason: None,
625 headers,
626 }
627 }
628
629 pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
631 self.parse_with_config(buf, &ParserConfig::default())
632 }
633
634 fn parse_with_config(&mut self, buf: &'b [u8], config: &ParserConfig) -> Result<usize> {
635 let headers = mem::take(&mut self.headers);
636
637 unsafe {
640 let headers: *mut [Header<'_>] = headers;
641 let headers = headers as *mut [MaybeUninit<Header<'_>>];
642 match self.parse_with_config_and_uninit_headers(buf, config, &mut *headers) {
643 Ok(Status::Complete(idx)) => Ok(Status::Complete(idx)),
644 other => {
645 self.headers = &mut *(headers as *mut [Header<'_>]);
647 other
648 },
649 }
650 }
651 }
652
653 fn parse_with_config_and_uninit_headers(
654 &mut self,
655 buf: &'b [u8],
656 config: &ParserConfig,
657 mut headers: &'h mut [MaybeUninit<Header<'b>>],
658 ) -> Result<usize> {
659 let orig_len = buf.len();
660 let mut bytes = Bytes::new(buf);
661
662 complete!(skip_empty_lines(&mut bytes));
663 self.version = Some(complete!(parse_version(&mut bytes)));
664 space!(bytes or Error::Version);
665 if config.allow_multiple_spaces_in_response_status_delimiters {
666 complete!(skip_spaces(&mut bytes));
667 }
668 self.code = Some(complete!(parse_code(&mut bytes)));
669
670 match next!(bytes) {
680 b' ' => {
681 if config.allow_multiple_spaces_in_response_status_delimiters {
682 complete!(skip_spaces(&mut bytes));
683 }
684 bytes.slice();
685 self.reason = Some(complete!(parse_reason(&mut bytes)));
686 },
687 b'\r' => {
688 expect!(bytes.next() == b'\n' => Err(Error::Status));
689 bytes.slice();
690 self.reason = Some("");
691 },
692 b'\n' => {
693 bytes.slice();
694 self.reason = Some("");
695 }
696 _ => return Err(Error::Status),
697 }
698
699
700 let len = orig_len - bytes.len();
701 let headers_len = complete!(parse_headers_iter_uninit(
702 &mut headers,
703 &mut bytes,
704 &HeaderParserConfig {
705 allow_spaces_after_header_name: config.allow_spaces_after_header_name_in_responses,
706 allow_obsolete_multiline_headers: config.allow_obsolete_multiline_headers_in_responses,
707 allow_space_before_first_header_name: config.allow_space_before_first_header_name,
708 ignore_invalid_headers: config.ignore_invalid_headers_in_responses
709 }
710 ));
711 self.headers = unsafe { assume_init_slice(headers) };
713 Ok(Status::Complete(len + headers_len))
714 }
715}
716
717#[derive(Copy, Clone, Eq, PartialEq)]
719pub struct Header<'a> {
720 pub name: &'a str,
724 pub value: &'a [u8],
729}
730
731impl fmt::Debug for Header<'_> {
732 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
733 let mut f = f.debug_struct("Header");
734 f.field("name", &self.name);
735 if let Ok(value) = str::from_utf8(self.value) {
736 f.field("value", &value);
737 } else {
738 f.field("value", &self.value);
739 }
740 f.finish()
741 }
742}
743
744pub const EMPTY_HEADER: Header<'static> = Header { name: "", value: b"" };
753
754#[inline]
755#[doc(hidden)]
756#[allow(missing_docs)]
757pub fn parse_version(bytes: &mut Bytes) -> Result<u8> {
759 if let Some(eight) = bytes.peek_n::<[u8; 8]>(8) {
760 let h10: u64 = u64::from_ne_bytes(*b"HTTP/1.0");
762 let h11: u64 = u64::from_ne_bytes(*b"HTTP/1.1");
763 unsafe {
765 bytes.advance(8);
766 }
767 let block = u64::from_ne_bytes(eight);
768 return if block == h10 {
770 Ok(Status::Complete(0))
771 } else if block == h11 {
772 Ok(Status::Complete(1))
773 } else {
774 Err(Error::Version)
775 };
776 }
777
778 expect!(bytes.next() == b'H' => Err(Error::Version));
783 expect!(bytes.next() == b'T' => Err(Error::Version));
784 expect!(bytes.next() == b'T' => Err(Error::Version));
785 expect!(bytes.next() == b'P' => Err(Error::Version));
786 expect!(bytes.next() == b'/' => Err(Error::Version));
787 expect!(bytes.next() == b'1' => Err(Error::Version));
788 expect!(bytes.next() == b'.' => Err(Error::Version));
789 Ok(Status::Partial)
790}
791
792#[inline]
793#[doc(hidden)]
794#[allow(missing_docs)]
795pub fn parse_method<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
797 const GET: [u8; 4] = *b"GET ";
798 const POST: [u8; 4] = *b"POST";
799 match bytes.peek_n::<[u8; 4]>(4) {
800 Some(GET) => {
801 let method = unsafe {
803 bytes.advance(4); str::from_utf8_unchecked(bytes.slice_skip(1)) };
806 Ok(Status::Complete(method))
807 }
808 Some(POST) if unsafe { bytes.peek_ahead(4) } == Some(b' ') => {
814 let method = unsafe {
816 bytes.advance(5); str::from_utf8_unchecked(bytes.slice_skip(1)) };
819 Ok(Status::Complete(method))
820 }
821 _ => parse_token(bytes),
822 }
823}
824
825#[inline]
839fn parse_reason<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
840 let mut seen_obs_text = false;
841 loop {
842 let b = next!(bytes);
843 if b == b'\r' {
844 expect!(bytes.next() == b'\n' => Err(Error::Status));
845 return Ok(Status::Complete(
846 unsafe {
852 let bytes = bytes.slice_skip(2);
853 if !seen_obs_text {
854 str::from_utf8_unchecked(bytes)
856 } else {
857 ""
859 }
860 },
861 ));
862 } else if b == b'\n' {
863 return Ok(Status::Complete(
864 unsafe {
868 let bytes = bytes.slice_skip(1);
869 if !seen_obs_text {
870 str::from_utf8_unchecked(bytes)
872 } else {
873 ""
875 }
876 },
877 ));
878 } else if !(b == 0x09 || b == b' ' || (0x21..=0x7E).contains(&b) || b >= 0x80) {
879 return Err(Error::Status);
880 } else if b >= 0x80 {
881 seen_obs_text = true;
882 }
883 }
884}
885
886#[inline]
887fn parse_token<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
888 let b = next!(bytes);
889 if !is_method_token(b) {
890 return Err(Error::Token);
892 }
893
894 loop {
895 let b = next!(bytes);
896 if b == b' ' {
897 return Ok(Status::Complete(
898 unsafe { str::from_utf8_unchecked(bytes.slice_skip(1)) },
900 ));
901 } else if !is_method_token(b) {
902 return Err(Error::Token);
903 }
904 }
905}
906
907#[inline]
908#[doc(hidden)]
909#[allow(missing_docs)]
910pub fn parse_uri<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
912 let start = bytes.pos();
913 simd::match_uri_vectored(bytes);
914 let end = bytes.pos();
915
916 if next!(bytes) == b' ' {
917 if end == start {
919 return Err(Error::Token);
920 }
921
922 match str::from_utf8(unsafe { bytes.slice_skip(1) }) {
924 Ok(uri) => Ok(Status::Complete(uri)),
925 Err(_) => Err(Error::Token),
926 }
927 } else {
928 Err(Error::Token)
929 }
930}
931
932#[inline]
933fn parse_code(bytes: &mut Bytes<'_>) -> Result<u16> {
934 let hundreds = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
935 let tens = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
936 let ones = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
937
938 Ok(Status::Complete((hundreds - b'0') as u16 * 100 +
939 (tens - b'0') as u16 * 10 +
940 (ones - b'0') as u16))
941}
942
943pub fn parse_headers<'b: 'h, 'h>(
962 src: &'b [u8],
963 mut dst: &'h mut [Header<'b>],
964) -> Result<(usize, &'h [Header<'b>])> {
965 let mut iter = Bytes::new(src);
966 let pos = complete!(parse_headers_iter(&mut dst, &mut iter, &HeaderParserConfig::default()));
967 Ok(Status::Complete((pos, dst)))
968}
969
970#[inline]
971fn parse_headers_iter<'a>(
972 headers: &mut &mut [Header<'a>],
973 bytes: &mut Bytes<'a>,
974 config: &HeaderParserConfig,
975) -> Result<usize> {
976 parse_headers_iter_uninit(
977 unsafe { deinit_slice_mut(headers) },
979 bytes,
980 config,
981 )
982}
983
984unsafe fn deinit_slice_mut<'a, 'b, T>(s: &'a mut &'b mut [T]) -> &'a mut &'b mut [MaybeUninit<T>] {
985 let s: *mut &mut [T] = s;
986 let s = s as *mut &mut [MaybeUninit<T>];
987 &mut *s
988}
989unsafe fn assume_init_slice<T>(s: &mut [MaybeUninit<T>]) -> &mut [T] {
990 let s: *mut [MaybeUninit<T>] = s;
991 let s = s as *mut [T];
992 &mut *s
993}
994
995#[derive(Clone, Debug, Default)]
996struct HeaderParserConfig {
997 allow_spaces_after_header_name: bool,
998 allow_obsolete_multiline_headers: bool,
999 allow_space_before_first_header_name: bool,
1000 ignore_invalid_headers: bool,
1001}
1002
1003fn parse_headers_iter_uninit<'a>(
1013 headers: &mut &mut [MaybeUninit<Header<'a>>],
1014 bytes: &mut Bytes<'a>,
1015 config: &HeaderParserConfig
1016) -> Result<usize> {
1017
1018 struct ShrinkOnDrop<'r1, 'r2, 'a> {
1023 headers: &'r1 mut &'r2 mut [MaybeUninit<Header<'a>>],
1024 num_headers: usize,
1025 }
1026
1027 impl Drop for ShrinkOnDrop<'_, '_, '_> {
1028 fn drop(&mut self) {
1029 let headers = mem::take(self.headers);
1030
1031 let headers = unsafe { headers.get_unchecked_mut(..self.num_headers) };
1033
1034 *self.headers = headers;
1035 }
1036 }
1037
1038 let mut autoshrink = ShrinkOnDrop {
1039 headers,
1040 num_headers: 0,
1041 };
1042 let start = bytes.as_ref().as_ptr() as usize;
1044 let mut result = Err(Error::TooManyHeaders);
1045
1046 let mut iter = autoshrink.headers.iter_mut();
1047
1048 macro_rules! maybe_continue_after_obsolete_line_folding {
1049 ($bytes:ident, $label:lifetime) => {
1050 if config.allow_obsolete_multiline_headers {
1051 match $bytes.peek() {
1052 None => {
1053 return Ok(Status::Partial);
1057 }
1058 Some(b' ') | Some(b'\t') => {
1059 continue $label;
1061 }
1062 _ => {
1063 },
1068 }
1069 }
1070 }
1071 }
1072
1073 'headers: loop {
1074 macro_rules! handle_invalid_char {
1078 ($bytes:ident, $b:ident, $err:ident) => {
1079 if !config.ignore_invalid_headers {
1080 return Err(Error::$err);
1081 }
1082
1083 let mut b = $b;
1084
1085 loop {
1086 if b == b'\r' {
1087 expect!(bytes.next() == b'\n' => Err(Error::$err));
1088 break;
1089 }
1090 if b == b'\n' {
1091 break;
1092 }
1093 if b == b'\0' {
1094 return Err(Error::$err);
1095 }
1096 b = next!($bytes);
1097 }
1098
1099 $bytes.slice();
1100
1101 continue 'headers;
1102 };
1103 }
1104
1105 let b = next!(bytes);
1107 if b == b'\r' {
1108 expect!(bytes.next() == b'\n' => Err(Error::NewLine));
1109 let end = bytes.as_ref().as_ptr() as usize;
1110 result = Ok(Status::Complete(end - start));
1111 break;
1112 }
1113 if b == b'\n' {
1114 let end = bytes.as_ref().as_ptr() as usize;
1115 result = Ok(Status::Complete(end - start));
1116 break;
1117 }
1118 if !is_header_name_token(b) {
1119 if config.allow_space_before_first_header_name
1120 && autoshrink.num_headers == 0
1121 && (b == b' ' || b == b'\t')
1122 {
1123 while let Some(peek) = bytes.peek() {
1125 if peek == b' ' || peek == b'\t' {
1126 next!(bytes);
1127 } else {
1128 break;
1129 }
1130 }
1131 bytes.slice();
1132 continue 'headers;
1133 } else {
1134 handle_invalid_char!(bytes, b, HeaderName);
1135 }
1136 }
1137
1138 #[allow(clippy::never_loop)]
1139 let header_name: &str = 'name: loop {
1141 simd::match_header_name_vectored(bytes);
1142 let mut b = next!(bytes);
1143
1144 let bslice = unsafe { bytes.slice_skip(1) };
1146 let name = unsafe { str::from_utf8_unchecked(bslice) };
1149
1150 if b == b':' {
1151 break 'name name;
1152 }
1153
1154 if config.allow_spaces_after_header_name {
1155 while b == b' ' || b == b'\t' {
1156 b = next!(bytes);
1157
1158 if b == b':' {
1159 bytes.slice();
1160 break 'name name;
1161 }
1162 }
1163 }
1164
1165 handle_invalid_char!(bytes, b, HeaderName);
1166 };
1167
1168 let mut b;
1169
1170 #[allow(clippy::never_loop)]
1171 let value_slice = 'value: loop {
1172 'whitespace_after_colon: loop {
1174 b = next!(bytes);
1175 if b == b' ' || b == b'\t' {
1176 bytes.slice();
1177 continue 'whitespace_after_colon;
1178 }
1179 if is_header_value_token(b) {
1180 break 'whitespace_after_colon;
1181 }
1182
1183 if b == b'\r' {
1184 expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
1185 } else if b != b'\n' {
1186 handle_invalid_char!(bytes, b, HeaderValue);
1187 }
1188
1189 maybe_continue_after_obsolete_line_folding!(bytes, 'whitespace_after_colon);
1190
1191 let whitespace_slice = bytes.slice();
1192
1193 break 'value &whitespace_slice[0..0];
1196 }
1197
1198 'value_lines: loop {
1199 simd::match_header_value_vectored(bytes);
1202 let b = next!(bytes);
1203
1204 let skip = if b == b'\r' {
1206 expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
1207 2
1208 } else if b == b'\n' {
1209 1
1210 } else {
1211 handle_invalid_char!(bytes, b, HeaderValue);
1212 };
1213
1214 maybe_continue_after_obsolete_line_folding!(bytes, 'value_lines);
1215
1216 unsafe {
1218 break 'value bytes.slice_skip(skip);
1219 }
1220 }
1221 };
1222
1223 let uninit_header = match iter.next() {
1224 Some(header) => header,
1225 None => break 'headers
1226 };
1227
1228 let header_value = if let Some(last_visible) = value_slice
1230 .iter()
1231 .rposition(|b| *b != b' ' && *b != b'\t' && *b != b'\r' && *b != b'\n')
1232 {
1233 &value_slice[0..last_visible+1]
1235 } else {
1236 value_slice
1239 };
1240
1241 *uninit_header = MaybeUninit::new(Header {
1242 name: header_name,
1243 value: header_value,
1244 });
1245 autoshrink.num_headers += 1;
1246 }
1247
1248 result
1249}
1250
1251pub fn parse_chunk_size(buf: &[u8])
1264 -> result::Result<Status<(usize, u64)>, InvalidChunkSize> {
1265 const RADIX: u64 = 16;
1266 let mut bytes = Bytes::new(buf);
1267 let mut size = 0;
1268 let mut in_chunk_size = true;
1269 let mut in_ext = false;
1270 let mut count = 0;
1271 loop {
1272 let b = next!(bytes);
1273 match b {
1274 b'0' ..= b'9' if in_chunk_size => {
1275 if count > 15 {
1276 return Err(InvalidChunkSize);
1277 }
1278 count += 1;
1279 if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
1280 return Err(InvalidChunkSize);
1285 }
1286 size *= RADIX;
1287 size += (b - b'0') as u64;
1288 },
1289 b'a' ..= b'f' if in_chunk_size => {
1290 if count > 15 {
1291 return Err(InvalidChunkSize);
1292 }
1293 count += 1;
1294 if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
1295 return Err(InvalidChunkSize);
1296 }
1297 size *= RADIX;
1298 size += (b + 10 - b'a') as u64;
1299 }
1300 b'A' ..= b'F' if in_chunk_size => {
1301 if count > 15 {
1302 return Err(InvalidChunkSize);
1303 }
1304 count += 1;
1305 if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
1306 return Err(InvalidChunkSize);
1307 }
1308 size *= RADIX;
1309 size += (b + 10 - b'A') as u64;
1310 }
1311 b'\r' => {
1312 match next!(bytes) {
1313 b'\n' => break,
1314 _ => return Err(InvalidChunkSize),
1315 }
1316 }
1317 b';' if !in_ext => {
1319 in_ext = true;
1320 in_chunk_size = false;
1321 }
1322 b'\t' | b' ' if !in_ext && !in_chunk_size => {}
1325 b'\t' | b' ' if in_chunk_size => in_chunk_size = false,
1327 _ if in_ext => {}
1333 _ => return Err(InvalidChunkSize),
1336 }
1337 }
1338 Ok(Status::Complete((bytes.pos(), size)))
1339}
1340
1341#[cfg(test)]
1342mod tests {
1343 use super::{Error, Request, Response, Status, EMPTY_HEADER, parse_chunk_size};
1344
1345 const NUM_OF_HEADERS: usize = 4;
1346
1347 macro_rules! req {
1348 ($name:ident, $buf:expr, |$arg:ident| $body:expr) => (
1349 req! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
1350 );
1351 ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => (
1352 #[test]
1353 fn $name() {
1354 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1355 let mut req = Request::new(&mut headers[..]);
1356 let status = req.parse($buf.as_ref());
1357 assert_eq!(status, $len);
1358 closure(req);
1359
1360 fn closure($arg: Request) {
1361 $body
1362 }
1363 }
1364 )
1365 }
1366
1367 req! {
1368 test_request_simple,
1369 b"GET / HTTP/1.1\r\n\r\n",
1370 |req| {
1371 assert_eq!(req.method.unwrap(), "GET");
1372 assert_eq!(req.path.unwrap(), "/");
1373 assert_eq!(req.version.unwrap(), 1);
1374 assert_eq!(req.headers.len(), 0);
1375 }
1376 }
1377
1378 req! {
1379 test_request_simple_with_query_params,
1380 b"GET /thing?data=a HTTP/1.1\r\n\r\n",
1381 |req| {
1382 assert_eq!(req.method.unwrap(), "GET");
1383 assert_eq!(req.path.unwrap(), "/thing?data=a");
1384 assert_eq!(req.version.unwrap(), 1);
1385 assert_eq!(req.headers.len(), 0);
1386 }
1387 }
1388
1389 req! {
1390 test_request_simple_with_whatwg_query_params,
1391 b"GET /thing?data=a^ HTTP/1.1\r\n\r\n",
1392 |req| {
1393 assert_eq!(req.method.unwrap(), "GET");
1394 assert_eq!(req.path.unwrap(), "/thing?data=a^");
1395 assert_eq!(req.version.unwrap(), 1);
1396 assert_eq!(req.headers.len(), 0);
1397 }
1398 }
1399
1400 req! {
1401 test_request_headers,
1402 b"GET / HTTP/1.1\r\nHost: foo.com\r\nCookie: \r\n\r\n",
1403 |req| {
1404 assert_eq!(req.method.unwrap(), "GET");
1405 assert_eq!(req.path.unwrap(), "/");
1406 assert_eq!(req.version.unwrap(), 1);
1407 assert_eq!(req.headers.len(), 2);
1408 assert_eq!(req.headers[0].name, "Host");
1409 assert_eq!(req.headers[0].value, b"foo.com");
1410 assert_eq!(req.headers[1].name, "Cookie");
1411 assert_eq!(req.headers[1].value, b"");
1412 }
1413 }
1414
1415 req! {
1416 test_request_headers_optional_whitespace,
1417 b"GET / HTTP/1.1\r\nHost: \tfoo.com\t \r\nCookie: \t \r\n\r\n",
1418 |req| {
1419 assert_eq!(req.method.unwrap(), "GET");
1420 assert_eq!(req.path.unwrap(), "/");
1421 assert_eq!(req.version.unwrap(), 1);
1422 assert_eq!(req.headers.len(), 2);
1423 assert_eq!(req.headers[0].name, "Host");
1424 assert_eq!(req.headers[0].value, b"foo.com");
1425 assert_eq!(req.headers[1].name, "Cookie");
1426 assert_eq!(req.headers[1].value, b"");
1427 }
1428 }
1429
1430 req! {
1431 test_request_header_value_htab_short,
1433 b"GET / HTTP/1.1\r\nUser-Agent: some\tagent\r\n\r\n",
1434 |req| {
1435 assert_eq!(req.method.unwrap(), "GET");
1436 assert_eq!(req.path.unwrap(), "/");
1437 assert_eq!(req.version.unwrap(), 1);
1438 assert_eq!(req.headers.len(), 1);
1439 assert_eq!(req.headers[0].name, "User-Agent");
1440 assert_eq!(req.headers[0].value, b"some\tagent");
1441 }
1442 }
1443
1444 req! {
1445 test_request_header_value_htab_med,
1447 b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\tagent\r\n\r\n",
1448 |req| {
1449 assert_eq!(req.method.unwrap(), "GET");
1450 assert_eq!(req.path.unwrap(), "/");
1451 assert_eq!(req.version.unwrap(), 1);
1452 assert_eq!(req.headers.len(), 1);
1453 assert_eq!(req.headers[0].name, "User-Agent");
1454 assert_eq!(req.headers[0].value, b"1234567890some\tagent");
1455 }
1456 }
1457
1458 req! {
1459 test_request_header_value_htab_long,
1461 b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\t1234567890agent1234567890\r\n\r\n",
1462 |req| {
1463 assert_eq!(req.method.unwrap(), "GET");
1464 assert_eq!(req.path.unwrap(), "/");
1465 assert_eq!(req.version.unwrap(), 1);
1466 assert_eq!(req.headers.len(), 1);
1467 assert_eq!(req.headers[0].name, "User-Agent");
1468 assert_eq!(req.headers[0].value, &b"1234567890some\t1234567890agent1234567890"[..]);
1469 }
1470 }
1471
1472 req! {
1473 test_request_header_no_space_after_colon,
1475 b"GET / HTTP/1.1\r\nUser-Agent:omg-no-space1234567890some1234567890agent1234567890\r\n\r\n",
1476 |req| {
1477 assert_eq!(req.method.unwrap(), "GET");
1478 assert_eq!(req.path.unwrap(), "/");
1479 assert_eq!(req.version.unwrap(), 1);
1480 assert_eq!(req.headers.len(), 1);
1481 assert_eq!(req.headers[0].name, "User-Agent");
1482 assert_eq!(req.headers[0].value, &b"omg-no-space1234567890some1234567890agent1234567890"[..]);
1483 }
1484 }
1485
1486 req! {
1487 test_request_headers_max,
1488 b"GET / HTTP/1.1\r\nA: A\r\nB: B\r\nC: C\r\nD: D\r\n\r\n",
1489 |req| {
1490 assert_eq!(req.headers.len(), NUM_OF_HEADERS);
1491 }
1492 }
1493
1494 req! {
1495 test_request_multibyte,
1496 b"GET / HTTP/1.1\r\nHost: foo.com\r\nUser-Agent: \xe3\x81\xb2\xe3/1.0\r\n\r\n",
1497 |req| {
1498 assert_eq!(req.method.unwrap(), "GET");
1499 assert_eq!(req.path.unwrap(), "/");
1500 assert_eq!(req.version.unwrap(), 1);
1501 assert_eq!(req.headers.len(), 2);
1502 assert_eq!(req.headers[0].name, "Host");
1503 assert_eq!(req.headers[0].value, b"foo.com");
1504 assert_eq!(req.headers[1].name, "User-Agent");
1505 assert_eq!(req.headers[1].value, b"\xe3\x81\xb2\xe3/1.0");
1506 }
1507 }
1508
1509 req! {
1511 test_request_one_byte_method,
1512 b"G", Ok(Status::Partial),
1513 |_req| {}
1514 }
1515
1516 req! {
1518 test_request_partial_method,
1519 b"GE", Ok(Status::Partial),
1520 |_req| {}
1521 }
1522
1523 req! {
1525 test_request_method_no_delimiter,
1526 b"GET", Ok(Status::Partial),
1527 |_req| {}
1528 }
1529
1530 req! {
1533 test_request_method_only,
1534 b"GET ", Ok(Status::Partial),
1535 |_req| {}
1536 }
1537
1538 req! {
1539 test_request_partial,
1540 b"GET / HTTP/1.1\r\n\r", Ok(Status::Partial),
1541 |_req| {}
1542 }
1543
1544 req! {
1545 test_request_partial_version,
1546 b"GET / HTTP/1.", Ok(Status::Partial),
1547 |_req| {}
1548 }
1549
1550 req! {
1551 test_request_method_path_no_delimiter,
1552 b"GET /", Ok(Status::Partial),
1553 |_req| {}
1554 }
1555
1556 req! {
1557 test_request_method_path_only,
1558 b"GET / ", Ok(Status::Partial),
1559 |_req| {}
1560 }
1561
1562 req! {
1563 test_request_partial_parses_headers_as_much_as_it_can,
1564 b"GET / HTTP/1.1\r\nHost: yolo\r\n",
1565 Ok(crate::Status::Partial),
1566 |req| {
1567 assert_eq!(req.method.unwrap(), "GET");
1568 assert_eq!(req.path.unwrap(), "/");
1569 assert_eq!(req.version.unwrap(), 1);
1570 assert_eq!(req.headers.len(), NUM_OF_HEADERS); assert_eq!(req.headers[0].name, "Host");
1572 assert_eq!(req.headers[0].value, b"yolo");
1573 }
1574 }
1575
1576 req! {
1577 test_request_newlines,
1578 b"GET / HTTP/1.1\nHost: foo.bar\n\n",
1579 |_r| {}
1580 }
1581
1582 req! {
1583 test_request_empty_lines_prefix,
1584 b"\r\n\r\nGET / HTTP/1.1\r\n\r\n",
1585 |req| {
1586 assert_eq!(req.method.unwrap(), "GET");
1587 assert_eq!(req.path.unwrap(), "/");
1588 assert_eq!(req.version.unwrap(), 1);
1589 assert_eq!(req.headers.len(), 0);
1590 }
1591 }
1592
1593 req! {
1594 test_request_empty_lines_prefix_lf_only,
1595 b"\n\nGET / HTTP/1.1\n\n",
1596 |req| {
1597 assert_eq!(req.method.unwrap(), "GET");
1598 assert_eq!(req.path.unwrap(), "/");
1599 assert_eq!(req.version.unwrap(), 1);
1600 assert_eq!(req.headers.len(), 0);
1601 }
1602 }
1603
1604 req! {
1605 test_request_path_backslash,
1606 b"\n\nGET /\\?wayne\\=5 HTTP/1.1\n\n",
1607 |req| {
1608 assert_eq!(req.method.unwrap(), "GET");
1609 assert_eq!(req.path.unwrap(), "/\\?wayne\\=5");
1610 assert_eq!(req.version.unwrap(), 1);
1611 assert_eq!(req.headers.len(), 0);
1612 }
1613 }
1614
1615 req! {
1616 test_request_with_invalid_token_delimiter,
1617 b"GET\n/ HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
1618 Err(crate::Error::Token),
1619 |_r| {}
1620 }
1621
1622
1623 req! {
1624 test_request_with_invalid_but_short_version,
1625 b"GET / HTTP/1!",
1626 Err(crate::Error::Version),
1627 |_r| {}
1628 }
1629
1630 req! {
1631 test_request_with_empty_method,
1632 b" / HTTP/1.1\r\n\r\n",
1633 Err(crate::Error::Token),
1634 |_r| {}
1635 }
1636
1637 req! {
1638 test_request_with_empty_path,
1639 b"GET HTTP/1.1\r\n\r\n",
1640 Err(crate::Error::Token),
1641 |_r| {}
1642 }
1643
1644 req! {
1645 test_request_with_empty_method_and_path,
1646 b" HTTP/1.1\r\n\r\n",
1647 Err(crate::Error::Token),
1648 |_r| {}
1649 }
1650
1651 macro_rules! res {
1652 ($name:ident, $buf:expr, |$arg:ident| $body:expr) => (
1653 res! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
1654 );
1655 ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => (
1656 #[test]
1657 fn $name() {
1658 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1659 let mut res = Response::new(&mut headers[..]);
1660 let status = res.parse($buf.as_ref());
1661 assert_eq!(status, $len);
1662 closure(res);
1663
1664 fn closure($arg: Response) {
1665 $body
1666 }
1667 }
1668 )
1669 }
1670
1671 res! {
1672 test_response_simple,
1673 b"HTTP/1.1 200 OK\r\n\r\n",
1674 |res| {
1675 assert_eq!(res.version.unwrap(), 1);
1676 assert_eq!(res.code.unwrap(), 200);
1677 assert_eq!(res.reason.unwrap(), "OK");
1678 }
1679 }
1680
1681 res! {
1682 test_response_newlines,
1683 b"HTTP/1.0 403 Forbidden\nServer: foo.bar\n\n",
1684 |_r| {}
1685 }
1686
1687 res! {
1688 test_response_reason_missing,
1689 b"HTTP/1.1 200 \r\n\r\n",
1690 |res| {
1691 assert_eq!(res.version.unwrap(), 1);
1692 assert_eq!(res.code.unwrap(), 200);
1693 assert_eq!(res.reason.unwrap(), "");
1694 }
1695 }
1696
1697 res! {
1698 test_response_reason_missing_no_space,
1699 b"HTTP/1.1 200\r\n\r\n",
1700 |res| {
1701 assert_eq!(res.version.unwrap(), 1);
1702 assert_eq!(res.code.unwrap(), 200);
1703 assert_eq!(res.reason.unwrap(), "");
1704 }
1705 }
1706
1707 res! {
1708 test_response_reason_missing_no_space_with_headers,
1709 b"HTTP/1.1 200\r\nFoo: bar\r\n\r\n",
1710 |res| {
1711 assert_eq!(res.version.unwrap(), 1);
1712 assert_eq!(res.code.unwrap(), 200);
1713 assert_eq!(res.reason.unwrap(), "");
1714 assert_eq!(res.headers.len(), 1);
1715 assert_eq!(res.headers[0].name, "Foo");
1716 assert_eq!(res.headers[0].value, b"bar");
1717 }
1718 }
1719
1720 res! {
1721 test_response_reason_with_space_and_tab,
1722 b"HTTP/1.1 101 Switching Protocols\t\r\n\r\n",
1723 |res| {
1724 assert_eq!(res.version.unwrap(), 1);
1725 assert_eq!(res.code.unwrap(), 101);
1726 assert_eq!(res.reason.unwrap(), "Switching Protocols\t");
1727 }
1728 }
1729
1730 static RESPONSE_REASON_WITH_OBS_TEXT_BYTE: &[u8] = b"HTTP/1.1 200 X\xFFZ\r\n\r\n";
1731 res! {
1732 test_response_reason_with_obsolete_text_byte,
1733 RESPONSE_REASON_WITH_OBS_TEXT_BYTE,
1734 |res| {
1735 assert_eq!(res.version.unwrap(), 1);
1736 assert_eq!(res.code.unwrap(), 200);
1737 assert_eq!(res.reason.unwrap(), "");
1739 }
1740 }
1741
1742 res! {
1743 test_response_reason_with_nul_byte,
1744 b"HTTP/1.1 200 \x00\r\n\r\n",
1745 Err(crate::Error::Status),
1746 |_res| {}
1747 }
1748
1749 res! {
1750 test_response_version_missing_space,
1751 b"HTTP/1.1",
1752 Ok(Status::Partial),
1753 |_res| {}
1754 }
1755
1756 res! {
1757 test_response_code_missing_space,
1758 b"HTTP/1.1 200",
1759 Ok(Status::Partial),
1760 |_res| {}
1761 }
1762
1763 res! {
1764 test_response_partial_parses_headers_as_much_as_it_can,
1765 b"HTTP/1.1 200 OK\r\nServer: yolo\r\n",
1766 Ok(crate::Status::Partial),
1767 |res| {
1768 assert_eq!(res.version.unwrap(), 1);
1769 assert_eq!(res.code.unwrap(), 200);
1770 assert_eq!(res.reason.unwrap(), "OK");
1771 assert_eq!(res.headers.len(), NUM_OF_HEADERS); assert_eq!(res.headers[0].name, "Server");
1773 assert_eq!(res.headers[0].value, b"yolo");
1774 }
1775 }
1776
1777 res! {
1778 test_response_empty_lines_prefix_lf_only,
1779 b"\n\nHTTP/1.1 200 OK\n\n",
1780 |_res| {}
1781 }
1782
1783 res! {
1784 test_response_no_cr,
1785 b"HTTP/1.0 200\nContent-type: text/html\n\n",
1786 |res| {
1787 assert_eq!(res.version.unwrap(), 0);
1788 assert_eq!(res.code.unwrap(), 200);
1789 assert_eq!(res.reason.unwrap(), "");
1790 assert_eq!(res.headers.len(), 1);
1791 assert_eq!(res.headers[0].name, "Content-type");
1792 assert_eq!(res.headers[0].value, b"text/html");
1793 }
1794 }
1795
1796 #[test]
1798 fn partial_permutations() {
1799 let req_str = "GET / HTTP/1.1\r\n\r\n";
1800 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
1801 let mut req = Request::new(&mut headers[..]);
1802 for i in 0..req_str.len() {
1803 let status = req.parse(req_str[..i].as_bytes());
1804 assert_eq!(
1805 status,
1806 Ok(Status::Partial),
1807 "partial request line should return partial. \
1808 Portion which failed: '{seg}' (below {i})",
1809 seg = &req_str[..i]
1810 );
1811 }
1812 }
1813
1814 static RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
1815 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\nBread: baguette\r\n\r\n";
1816
1817 #[test]
1818 fn test_forbid_response_with_whitespace_between_header_name_and_colon() {
1819 let mut headers = [EMPTY_HEADER; 2];
1820 let mut response = Response::new(&mut headers[..]);
1821 let result = response.parse(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1822
1823 assert_eq!(result, Err(crate::Error::HeaderName));
1824 }
1825
1826 #[test]
1827 fn test_allow_response_with_whitespace_between_header_name_and_colon() {
1828 let mut headers = [EMPTY_HEADER; 2];
1829 let mut response = Response::new(&mut headers[..]);
1830 let result = crate::ParserConfig::default()
1831 .allow_spaces_after_header_name_in_responses(true)
1832 .parse_response(&mut response, RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1833
1834 assert_eq!(result, Ok(Status::Complete(77)));
1835 assert_eq!(response.version.unwrap(), 1);
1836 assert_eq!(response.code.unwrap(), 200);
1837 assert_eq!(response.reason.unwrap(), "OK");
1838 assert_eq!(response.headers.len(), 2);
1839 assert_eq!(response.headers[0].name, "Access-Control-Allow-Credentials");
1840 assert_eq!(response.headers[0].value, &b"true"[..]);
1841 assert_eq!(response.headers[1].name, "Bread");
1842 assert_eq!(response.headers[1].value, &b"baguette"[..]);
1843 }
1844
1845 #[test]
1846 fn test_ignore_header_line_with_whitespaces_after_header_name_in_response() {
1847 let mut headers = [EMPTY_HEADER; 2];
1848 let mut response = Response::new(&mut headers[..]);
1849 let result = crate::ParserConfig::default()
1850 .ignore_invalid_headers_in_responses(true)
1851 .parse_response(&mut response, RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1852
1853 assert_eq!(result, Ok(Status::Complete(77)));
1854 assert_eq!(response.version.unwrap(), 1);
1855 assert_eq!(response.code.unwrap(), 200);
1856 assert_eq!(response.reason.unwrap(), "OK");
1857 assert_eq!(response.headers.len(), 1);
1858 assert_eq!(response.headers[0].name, "Bread");
1859 assert_eq!(response.headers[0].value, &b"baguette"[..]);
1860 }
1861
1862 static REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
1863 b"GET / HTTP/1.1\r\nHost : localhost\r\n\r\n";
1864
1865 #[test]
1866 fn test_forbid_request_with_whitespace_between_header_name_and_colon() {
1867 let mut headers = [EMPTY_HEADER; 1];
1868 let mut request = Request::new(&mut headers[..]);
1869 let result = request.parse(REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1870
1871 assert_eq!(result, Err(crate::Error::HeaderName));
1872 }
1873
1874 #[test]
1875 fn test_ignore_header_line_with_whitespaces_after_header_name_in_request() {
1876 let mut headers = [EMPTY_HEADER; 2];
1877 let mut request = Request::new(&mut headers[..]);
1878 let result = crate::ParserConfig::default()
1879 .ignore_invalid_headers_in_requests(true)
1880 .parse_request(&mut request, REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
1881
1882 assert_eq!(result, Ok(Status::Complete(36)));
1883 }
1884
1885 static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START: &[u8] =
1886 b"HTTP/1.1 200 OK\r\nLine-Folded-Header: \r\n \r\n hello there\r\n\r\n";
1887
1888 #[test]
1889 fn test_forbid_response_with_obsolete_line_folding_at_start() {
1890 let mut headers = [EMPTY_HEADER; 1];
1891 let mut response = Response::new(&mut headers[..]);
1892 let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
1893
1894 assert_eq!(result, Err(crate::Error::HeaderName));
1895 }
1896
1897 #[test]
1898 fn test_allow_response_with_obsolete_line_folding_at_start() {
1899 let mut headers = [EMPTY_HEADER; 1];
1900 let mut response = Response::new(&mut headers[..]);
1901 let result = crate::ParserConfig::default()
1902 .allow_obsolete_multiline_headers_in_responses(true)
1903 .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
1904
1905 assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START.len())));
1906 assert_eq!(response.version.unwrap(), 1);
1907 assert_eq!(response.code.unwrap(), 200);
1908 assert_eq!(response.reason.unwrap(), "OK");
1909 assert_eq!(response.headers.len(), 1);
1910 assert_eq!(response.headers[0].name, "Line-Folded-Header");
1911 assert_eq!(response.headers[0].value, &b"hello there"[..]);
1912 }
1913
1914 static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END: &[u8] =
1915 b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello there\r\n \r\n \r\n\r\n";
1916
1917 #[test]
1918 fn test_forbid_response_with_obsolete_line_folding_at_end() {
1919 let mut headers = [EMPTY_HEADER; 1];
1920 let mut response = Response::new(&mut headers[..]);
1921 let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
1922
1923 assert_eq!(result, Err(crate::Error::HeaderName));
1924 }
1925
1926 #[test]
1927 fn test_allow_response_with_obsolete_line_folding_at_end() {
1928 let mut headers = [EMPTY_HEADER; 1];
1929 let mut response = Response::new(&mut headers[..]);
1930 let result = crate::ParserConfig::default()
1931 .allow_obsolete_multiline_headers_in_responses(true)
1932 .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
1933
1934 assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END.len())));
1935 assert_eq!(response.version.unwrap(), 1);
1936 assert_eq!(response.code.unwrap(), 200);
1937 assert_eq!(response.reason.unwrap(), "OK");
1938 assert_eq!(response.headers.len(), 1);
1939 assert_eq!(response.headers[0].name, "Line-Folded-Header");
1940 assert_eq!(response.headers[0].value, &b"hello there"[..]);
1941 }
1942
1943 static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE: &[u8] =
1944 b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello \r\n \r\n there\r\n\r\n";
1945
1946 #[test]
1947 fn test_forbid_response_with_obsolete_line_folding_in_middle() {
1948 let mut headers = [EMPTY_HEADER; 1];
1949 let mut response = Response::new(&mut headers[..]);
1950 let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
1951
1952 assert_eq!(result, Err(crate::Error::HeaderName));
1953 }
1954
1955 #[test]
1956 fn test_allow_response_with_obsolete_line_folding_in_middle() {
1957 let mut headers = [EMPTY_HEADER; 1];
1958 let mut response = Response::new(&mut headers[..]);
1959 let result = crate::ParserConfig::default()
1960 .allow_obsolete_multiline_headers_in_responses(true)
1961 .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
1962
1963 assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE.len())));
1964 assert_eq!(response.version.unwrap(), 1);
1965 assert_eq!(response.code.unwrap(), 200);
1966 assert_eq!(response.reason.unwrap(), "OK");
1967 assert_eq!(response.headers.len(), 1);
1968 assert_eq!(response.headers[0].name, "Line-Folded-Header");
1969 assert_eq!(response.headers[0].value, &b"hello \r\n \r\n there"[..]);
1970 }
1971
1972 static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER: &[u8] =
1973 b"HTTP/1.1 200 OK\r\nLine-Folded-Header: \r\n \r\n \r\n\r\n";
1974
1975 #[test]
1976 fn test_forbid_response_with_obsolete_line_folding_in_empty_header() {
1977 let mut headers = [EMPTY_HEADER; 1];
1978 let mut response = Response::new(&mut headers[..]);
1979 let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER);
1980
1981 assert_eq!(result, Err(crate::Error::HeaderName));
1982 }
1983
1984 #[test]
1985 fn test_allow_response_with_obsolete_line_folding_in_empty_header() {
1986 let mut headers = [EMPTY_HEADER; 1];
1987 let mut response = Response::new(&mut headers[..]);
1988 let result = crate::ParserConfig::default()
1989 .allow_obsolete_multiline_headers_in_responses(true)
1990 .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER);
1991
1992 assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER.len())));
1993 assert_eq!(response.version.unwrap(), 1);
1994 assert_eq!(response.code.unwrap(), 200);
1995 assert_eq!(response.reason.unwrap(), "OK");
1996 assert_eq!(response.headers.len(), 1);
1997 assert_eq!(response.headers[0].name, "Line-Folded-Header");
1998 assert_eq!(response.headers[0].value, &b""[..]);
1999 }
2000
2001 #[test]
2002 fn test_chunk_size() {
2003 assert_eq!(parse_chunk_size(b"0\r\n"), Ok(Status::Complete((3, 0))));
2004 assert_eq!(parse_chunk_size(b"12\r\nchunk"), Ok(Status::Complete((4, 18))));
2005 assert_eq!(parse_chunk_size(b"3086d\r\n"), Ok(Status::Complete((7, 198765))));
2006 assert_eq!(parse_chunk_size(b"3735AB1;foo bar*\r\n"), Ok(Status::Complete((18, 57891505))));
2007 assert_eq!(parse_chunk_size(b"3735ab1 ; baz \r\n"), Ok(Status::Complete((16, 57891505))));
2008 assert_eq!(parse_chunk_size(b"77a65\r"), Ok(Status::Partial));
2009 assert_eq!(parse_chunk_size(b"ab"), Ok(Status::Partial));
2010 assert_eq!(parse_chunk_size(b"567f8a\rfoo"), Err(crate::InvalidChunkSize));
2011 assert_eq!(parse_chunk_size(b"567f8a\rfoo"), Err(crate::InvalidChunkSize));
2012 assert_eq!(parse_chunk_size(b"567xf8a\r\n"), Err(crate::InvalidChunkSize));
2013 assert_eq!(parse_chunk_size(b"ffffffffffffffff\r\n"), Ok(Status::Complete((18, u64::MAX))));
2014 assert_eq!(parse_chunk_size(b"1ffffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
2015 assert_eq!(parse_chunk_size(b"Affffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
2016 assert_eq!(parse_chunk_size(b"fffffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
2017 }
2018
2019 static RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] =
2020 b"HTTP/1.1 200 OK\r\n\r\n";
2021
2022 #[test]
2023 fn test_forbid_response_with_multiple_space_delimiters() {
2024 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2025 let mut response = Response::new(&mut headers[..]);
2026 let result = response.parse(RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
2027
2028 assert_eq!(result, Err(crate::Error::Status));
2029 }
2030
2031 #[test]
2032 fn test_allow_response_with_multiple_space_delimiters() {
2033 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2034 let mut response = Response::new(&mut headers[..]);
2035 let result = crate::ParserConfig::default()
2036 .allow_multiple_spaces_in_response_status_delimiters(true)
2037 .parse_response(&mut response, RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
2038
2039 assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS.len())));
2040 assert_eq!(response.version.unwrap(), 1);
2041 assert_eq!(response.code.unwrap(), 200);
2042 assert_eq!(response.reason.unwrap(), "OK");
2043 assert_eq!(response.headers.len(), 0);
2044 }
2045
2046 static RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] =
2049 b"HTTP/1.1 200\rOK\r\n\r\n";
2050
2051 #[test]
2052 fn test_forbid_response_with_weird_whitespace_delimiters() {
2053 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2054 let mut response = Response::new(&mut headers[..]);
2055 let result = response.parse(RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
2056
2057 assert_eq!(result, Err(crate::Error::Status));
2058 }
2059
2060 #[test]
2061 fn test_still_forbid_response_with_weird_whitespace_delimiters() {
2062 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2063 let mut response = Response::new(&mut headers[..]);
2064 let result = crate::ParserConfig::default()
2065 .allow_multiple_spaces_in_response_status_delimiters(true)
2066 .parse_response(&mut response, RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
2067 assert_eq!(result, Err(crate::Error::Status));
2068 }
2069
2070 static REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] =
2071 b"GET / HTTP/1.1\r\n\r\n";
2072
2073 #[test]
2074 fn test_forbid_request_with_multiple_space_delimiters() {
2075 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2076 let mut request = Request::new(&mut headers[..]);
2077 let result = request.parse(REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
2078
2079 assert_eq!(result, Err(crate::Error::Token));
2080 }
2081
2082 #[test]
2083 fn test_allow_request_with_multiple_space_delimiters() {
2084 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2085 let mut request = Request::new(&mut headers[..]);
2086 let result = crate::ParserConfig::default()
2087 .allow_multiple_spaces_in_request_line_delimiters(true)
2088 .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
2089
2090 assert_eq!(result, Ok(Status::Complete(REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS.len())));
2091 assert_eq!(request.method.unwrap(), "GET");
2092 assert_eq!(request.path.unwrap(), "/");
2093 assert_eq!(request.version.unwrap(), 1);
2094 assert_eq!(request.headers.len(), 0);
2095 }
2096
2097 static REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] =
2100 b"GET\r/\rHTTP/1.1\r\n\r\n";
2101
2102 #[test]
2103 fn test_forbid_request_with_weird_whitespace_delimiters() {
2104 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2105 let mut request = Request::new(&mut headers[..]);
2106 let result = request.parse(REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
2107
2108 assert_eq!(result, Err(crate::Error::Token));
2109 }
2110
2111 #[test]
2112 fn test_still_forbid_request_with_weird_whitespace_delimiters() {
2113 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2114 let mut request = Request::new(&mut headers[..]);
2115 let result = crate::ParserConfig::default()
2116 .allow_multiple_spaces_in_request_line_delimiters(true)
2117 .parse_request(&mut request, REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
2118 assert_eq!(result, Err(crate::Error::Token));
2119 }
2120
2121 static REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH: &[u8] = b"GET /foo ohno HTTP/1.1\r\n\r\n";
2122
2123 #[test]
2124 fn test_request_with_multiple_spaces_and_bad_path() {
2125 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2126 let mut request = Request::new(&mut headers[..]);
2127 let result = crate::ParserConfig::default()
2128 .allow_multiple_spaces_in_request_line_delimiters(true)
2129 .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH);
2130 assert_eq!(result, Err(crate::Error::Version));
2131 }
2132
2133 static REQUEST_WITH_DEL_IN_PATH: &[u8] = b"GET /foo\x7Fohno HTTP/1.1\r\n\r\n";
2137
2138 #[test]
2139 fn test_request_with_del_in_path() {
2140 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2141 let mut request = Request::new(&mut headers[..]);
2142 let result = crate::ParserConfig::default()
2143 .allow_multiple_spaces_in_request_line_delimiters(true)
2144 .parse_request(&mut request, crate::tests::REQUEST_WITH_DEL_IN_PATH);
2145 assert_eq!(result, Err(crate::Error::Token));
2146 }
2147
2148 #[test]
2149 #[cfg_attr(miri, ignore)] fn test_all_utf8_char_in_paths() {
2151 for i in 128..256 {
2153 for j in 128..256 {
2154 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2155 let mut request = Request::new(&mut headers[..]);
2156 let bytes = [i as u8, j as u8];
2157
2158 match core::str::from_utf8(&bytes) {
2159 Ok(s) => {
2160 let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
2161 let result = crate::ParserConfig::default()
2162 .allow_multiple_spaces_in_request_line_delimiters(true)
2163 .parse_request(&mut request, first_line.as_bytes());
2164
2165 assert_eq!(result, Ok(Status::Complete(20)), "failed for utf8 char i: {}, j: {}", i, j);
2166 },
2167 Err(_) => {
2168 let mut first_line = b"GET /".to_vec();
2169 first_line.extend(&bytes);
2170 first_line.extend(b" HTTP/1.1\r\n\r\n");
2171
2172 let result = crate::ParserConfig::default()
2173 .allow_multiple_spaces_in_request_line_delimiters(true)
2174 .parse_request(&mut request, first_line.as_slice());
2175
2176 assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}", i, j);
2177 },
2178 };
2179
2180 if i < 0xe0 {
2182 continue;
2183 }
2184
2185 for k in 128..256 {
2186 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2187 let mut request = Request::new(&mut headers[..]);
2188 let bytes = [i as u8, j as u8, k as u8];
2189
2190 match core::str::from_utf8(&bytes) {
2191 Ok(s) => {
2192 let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
2193 let result = crate::ParserConfig::default()
2194 .allow_multiple_spaces_in_request_line_delimiters(true)
2195 .parse_request(&mut request, first_line.as_bytes());
2196
2197 assert_eq!(result, Ok(Status::Complete(21)), "failed for utf8 char i: {}, j: {}, k: {}", i, j, k);
2198 },
2199 Err(_) => {
2200 let mut first_line = b"GET /".to_vec();
2201 first_line.extend(&bytes);
2202 first_line.extend(b" HTTP/1.1\r\n\r\n");
2203
2204 let result = crate::ParserConfig::default()
2205 .allow_multiple_spaces_in_request_line_delimiters(true)
2206 .parse_request(&mut request, first_line.as_slice());
2207
2208 assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}, k: {}", i, j, k);
2209 },
2210 };
2211
2212 if i < 0xf0 {
2214 continue;
2215 }
2216
2217 for l in 128..256 {
2218 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2219 let mut request = Request::new(&mut headers[..]);
2220 let bytes = [i as u8, j as u8, k as u8, l as u8];
2221
2222 match core::str::from_utf8(&bytes) {
2223 Ok(s) => {
2224 let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
2225 let result = crate::ParserConfig::default()
2226 .allow_multiple_spaces_in_request_line_delimiters(true)
2227 .parse_request(&mut request, first_line.as_bytes());
2228
2229 assert_eq!(result, Ok(Status::Complete(22)), "failed for utf8 char i: {}, j: {}, k: {}, l: {}", i, j, k, l);
2230 },
2231 Err(_) => {
2232 let mut first_line = b"GET /".to_vec();
2233 first_line.extend(&bytes);
2234 first_line.extend(b" HTTP/1.1\r\n\r\n");
2235
2236 let result = crate::ParserConfig::default()
2237 .allow_multiple_spaces_in_request_line_delimiters(true)
2238 .parse_request(&mut request, first_line.as_slice());
2239
2240 assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}, k: {}, l: {}", i, j, k, l);
2241 },
2242 };
2243 }
2244 }
2245 }
2246 }
2247 }
2248
2249 static RESPONSE_WITH_SPACES_IN_CODE: &[u8] = b"HTTP/1.1 99 200 OK\r\n\r\n";
2250
2251 #[test]
2252 fn test_response_with_spaces_in_code() {
2253 let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
2254 let mut response = Response::new(&mut headers[..]);
2255 let result = crate::ParserConfig::default()
2256 .allow_multiple_spaces_in_response_status_delimiters(true)
2257 .parse_response(&mut response, RESPONSE_WITH_SPACES_IN_CODE);
2258 assert_eq!(result, Err(crate::Error::Status));
2259 }
2260
2261 #[test]
2262 fn test_response_with_empty_header_name() {
2263 const RESPONSE: &[u8] =
2264 b"HTTP/1.1 200 OK\r\n: hello\r\nBread: baguette\r\n\r\n";
2265
2266 let mut headers = [EMPTY_HEADER; 2];
2267 let mut response = Response::new(&mut headers[..]);
2268
2269 let result = crate::ParserConfig::default()
2270 .allow_spaces_after_header_name_in_responses(true)
2271 .parse_response(&mut response, RESPONSE);
2272 assert_eq!(result, Err(crate::Error::HeaderName));
2273
2274 let result = crate::ParserConfig::default()
2275 .ignore_invalid_headers_in_responses(true)
2276 .parse_response(&mut response, RESPONSE);
2277 assert_eq!(result, Ok(Status::Complete(45)));
2278
2279 assert_eq!(response.version.unwrap(), 1);
2280 assert_eq!(response.code.unwrap(), 200);
2281 assert_eq!(response.reason.unwrap(), "OK");
2282 assert_eq!(response.headers.len(), 1);
2283 assert_eq!(response.headers[0].name, "Bread");
2284 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2285 }
2286
2287 #[test]
2288 fn test_request_with_empty_header_name() {
2289 const RESPONSE: &[u8] =
2290 b"GET / HTTP/1.1\r\n: hello\r\nBread: baguette\r\n\r\n";
2291
2292 let mut headers = [EMPTY_HEADER; 2];
2293 let mut request = Request::new(&mut headers[..]);
2294
2295 let result = crate::ParserConfig::default()
2296 .parse_request(&mut request, RESPONSE);
2297 assert_eq!(result, Err(crate::Error::HeaderName));
2298
2299 let result = crate::ParserConfig::default()
2300 .ignore_invalid_headers_in_requests(true)
2301 .parse_request(&mut request, RESPONSE);
2302 assert_eq!(result, Ok(Status::Complete(44)));
2303 }
2304
2305 #[test]
2306 fn test_request_with_whitespace_between_header_name_and_colon() {
2307 const REQUEST: &[u8] =
2308 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials : true\r\nBread: baguette\r\n\r\n";
2309
2310 let mut headers = [EMPTY_HEADER; 2];
2311 let mut request = Request::new(&mut headers[..]);
2312
2313 let result = crate::ParserConfig::default()
2314 .allow_spaces_after_header_name_in_responses(true)
2315 .parse_request(&mut request, REQUEST);
2316 assert_eq!(result, Err(crate::Error::HeaderName));
2317
2318 let result = crate::ParserConfig::default()
2319
2320 .ignore_invalid_headers_in_responses(true)
2321 .parse_request(&mut request, REQUEST);
2322 assert_eq!(result, Err(crate::Error::HeaderName));
2323 }
2324
2325 #[test]
2326 fn test_response_with_invalid_char_between_header_name_and_colon() {
2327 const RESPONSE: &[u8] =
2328 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\xFF : true\r\nBread: baguette\r\n\r\n";
2329
2330 let mut headers = [EMPTY_HEADER; 2];
2331 let mut response = Response::new(&mut headers[..]);
2332
2333 let result = crate::ParserConfig::default()
2334 .allow_spaces_after_header_name_in_responses(true)
2335 .parse_response(&mut response, RESPONSE);
2336 assert_eq!(result, Err(crate::Error::HeaderName));
2337
2338 let result = crate::ParserConfig::default()
2339 .ignore_invalid_headers_in_responses(true)
2340 .parse_response(&mut response, RESPONSE);
2341
2342 assert_eq!(result, Ok(Status::Complete(79)));
2343 assert_eq!(response.version.unwrap(), 1);
2344 assert_eq!(response.code.unwrap(), 200);
2345 assert_eq!(response.reason.unwrap(), "OK");
2346 assert_eq!(response.headers.len(), 1);
2347 assert_eq!(response.headers[0].name, "Bread");
2348 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2349 }
2350
2351 #[test]
2352 fn test_request_with_invalid_char_between_header_name_and_colon() {
2353 const REQUEST: &[u8] =
2354 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\xFF : true\r\nBread: baguette\r\n\r\n";
2355
2356 let mut headers = [EMPTY_HEADER; 2];
2357 let mut request = Request::new(&mut headers[..]);
2358
2359 let result = crate::ParserConfig::default()
2360 .parse_request(&mut request, REQUEST);
2361 assert_eq!(result, Err(crate::Error::HeaderName));
2362
2363 let result = crate::ParserConfig::default()
2364 .ignore_invalid_headers_in_requests(true)
2365 .parse_request(&mut request, REQUEST);
2366 assert_eq!(result, Ok(Status::Complete(78)));
2367 }
2368
2369 #[test]
2370 fn test_ignore_header_line_with_missing_colon_in_response() {
2371 const RESPONSE: &[u8] =
2372 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
2373
2374 let mut headers = [EMPTY_HEADER; 2];
2375 let mut response = Response::new(&mut headers[..]);
2376
2377 let result = crate::ParserConfig::default()
2378 .parse_response(&mut response, RESPONSE);
2379 assert_eq!(result, Err(crate::Error::HeaderName));
2380
2381 let result = crate::ParserConfig::default()
2382 .ignore_invalid_headers_in_responses(true)
2383 .parse_response(&mut response, RESPONSE);
2384 assert_eq!(result, Ok(Status::Complete(70)));
2385
2386 assert_eq!(response.version.unwrap(), 1);
2387 assert_eq!(response.code.unwrap(), 200);
2388 assert_eq!(response.reason.unwrap(), "OK");
2389 assert_eq!(response.headers.len(), 1);
2390 assert_eq!(response.headers[0].name, "Bread");
2391 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2392 }
2393
2394 #[test]
2395 fn test_ignore_header_line_with_missing_colon_in_request() {
2396 const REQUEST: &[u8] =
2397 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
2398
2399 let mut headers = [EMPTY_HEADER; 2];
2400 let mut request = Request::new(&mut headers[..]);
2401
2402 let result = crate::ParserConfig::default()
2403 .parse_request(&mut request, REQUEST);
2404 assert_eq!(result, Err(crate::Error::HeaderName));
2405
2406 let result = crate::ParserConfig::default()
2407 .ignore_invalid_headers_in_requests(true)
2408 .parse_request(&mut request, REQUEST);
2409 assert_eq!(result, Ok(Status::Complete(69)));
2410 }
2411
2412 #[test]
2413 fn test_response_header_with_missing_colon_with_folding() {
2414 const RESPONSE: &[u8] =
2415 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials \r\n hello\r\nBread: baguette\r\n\r\n";
2416
2417 let mut headers = [EMPTY_HEADER; 2];
2418 let mut response = Response::new(&mut headers[..]);
2419
2420 let result = crate::ParserConfig::default()
2421 .allow_obsolete_multiline_headers_in_responses(true)
2422 .allow_spaces_after_header_name_in_responses(true)
2423 .parse_response(&mut response, RESPONSE);
2424 assert_eq!(result, Err(crate::Error::HeaderName));
2425
2426 let result = crate::ParserConfig::default()
2427 .ignore_invalid_headers_in_responses(true)
2428 .parse_response(&mut response, RESPONSE);
2429 assert_eq!(result, Ok(Status::Complete(81)));
2430
2431 assert_eq!(response.version.unwrap(), 1);
2432 assert_eq!(response.code.unwrap(), 200);
2433 assert_eq!(response.reason.unwrap(), "OK");
2434 assert_eq!(response.headers.len(), 1);
2435 assert_eq!(response.headers[0].name, "Bread");
2436 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2437 }
2438
2439 #[test]
2440 fn test_request_header_with_missing_colon_with_folding() {
2441 const REQUEST: &[u8] =
2442 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials \r\n hello\r\nBread: baguette\r\n\r\n";
2443
2444 let mut headers = [EMPTY_HEADER; 2];
2445 let mut request = Request::new(&mut headers[..]);
2446
2447 let result = crate::ParserConfig::default()
2448 .parse_request(&mut request, REQUEST);
2449 assert_eq!(result, Err(crate::Error::HeaderName));
2450
2451 let result = crate::ParserConfig::default()
2452 .ignore_invalid_headers_in_requests(true)
2453 .parse_request(&mut request, REQUEST);
2454 assert_eq!(result, Ok(Status::Complete(80)));
2455 }
2456
2457 #[test]
2458 fn test_response_header_with_nul_in_header_name() {
2459 const RESPONSE: &[u8] =
2460 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
2461
2462 let mut headers = [EMPTY_HEADER; 2];
2463 let mut response = Response::new(&mut headers[..]);
2464
2465 let result = crate::ParserConfig::default()
2466 .parse_response(&mut response, RESPONSE);
2467 assert_eq!(result, Err(crate::Error::HeaderName));
2468
2469 let result = crate::ParserConfig::default()
2470 .ignore_invalid_headers_in_responses(true)
2471 .parse_response(&mut response, RESPONSE);
2472 assert_eq!(result, Err(crate::Error::HeaderName));
2473 }
2474
2475 #[test]
2476 fn test_request_header_with_nul_in_header_name() {
2477 const REQUEST: &[u8] =
2478 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
2479
2480 let mut headers = [EMPTY_HEADER; 2];
2481 let mut request = Request::new(&mut headers[..]);
2482
2483 let result = crate::ParserConfig::default()
2484 .parse_request(&mut request, REQUEST);
2485 assert_eq!(result, Err(crate::Error::HeaderName));
2486
2487 let result = crate::ParserConfig::default()
2488 .ignore_invalid_headers_in_requests(true)
2489 .parse_request(&mut request, REQUEST);
2490 assert_eq!(result, Err(crate::Error::HeaderName));
2491 }
2492
2493 #[test]
2494 fn test_header_with_cr_in_header_name() {
2495 const RESPONSE: &[u8] =
2496 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
2497
2498 let mut headers = [EMPTY_HEADER; 2];
2499 let mut response = Response::new(&mut headers[..]);
2500
2501 let result = crate::ParserConfig::default()
2502 .parse_response(&mut response, RESPONSE);
2503 assert_eq!(result, Err(crate::Error::HeaderName));
2504
2505 let result = crate::ParserConfig::default()
2506 .ignore_invalid_headers_in_responses(true)
2507 .parse_response(&mut response, RESPONSE);
2508 assert_eq!(result, Err(crate::Error::HeaderName));
2509
2510 const REQUEST: &[u8] =
2511 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
2512
2513 let mut headers = [EMPTY_HEADER; 2];
2514 let mut request = Request::new(&mut headers[..]);
2515
2516 let result = crate::ParserConfig::default()
2517 .parse_request(&mut request, REQUEST);
2518 assert_eq!(result, Err(crate::Error::HeaderName));
2519
2520 let result = crate::ParserConfig::default()
2521 .ignore_invalid_headers_in_requests(true)
2522 .parse_request(&mut request, REQUEST);
2523 assert_eq!(result, Err(crate::Error::HeaderName));
2524 }
2525
2526 #[test]
2527 fn test_header_with_nul_in_whitespace_before_colon() {
2528 const RESPONSE: &[u8] =
2529 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials \0: hello\r\nBread: baguette\r\n\r\n";
2530
2531 let mut headers = [EMPTY_HEADER; 2];
2532 let mut response = Response::new(&mut headers[..]);
2533
2534 let result = crate::ParserConfig::default()
2535 .allow_spaces_after_header_name_in_responses(true)
2536 .parse_response(&mut response, RESPONSE);
2537 assert_eq!(result, Err(crate::Error::HeaderName));
2538
2539 let result = crate::ParserConfig::default()
2540 .allow_spaces_after_header_name_in_responses(true)
2541 .ignore_invalid_headers_in_responses(true)
2542 .parse_response(&mut response, RESPONSE);
2543 assert_eq!(result, Err(crate::Error::HeaderName));
2544
2545 const REQUEST: &[u8] =
2546 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials \0: hello\r\nBread: baguette\r\n\r\n";
2547
2548 let mut headers = [EMPTY_HEADER; 2];
2549 let mut request = Request::new(&mut headers[..]);
2550
2551 let result = crate::ParserConfig::default()
2552 .ignore_invalid_headers_in_requests(true)
2553 .parse_request(&mut request, REQUEST);
2554 assert_eq!(result, Err(crate::Error::HeaderName));
2555 }
2556
2557 #[test]
2558 fn test_header_with_nul_in_value() {
2559 const RESPONSE: &[u8] =
2560 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
2561
2562 let mut headers = [EMPTY_HEADER; 2];
2563 let mut response = Response::new(&mut headers[..]);
2564
2565 let result = crate::ParserConfig::default()
2566 .parse_response(&mut response, RESPONSE);
2567 assert_eq!(result, Err(crate::Error::HeaderValue));
2568
2569 let result = crate::ParserConfig::default()
2570 .ignore_invalid_headers_in_responses(true)
2571 .parse_response(&mut response, RESPONSE);
2572 assert_eq!(result, Err(crate::Error::HeaderValue));
2573
2574 const REQUEST: &[u8] =
2575 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
2576
2577 let mut headers = [EMPTY_HEADER; 2];
2578 let mut request = Request::new(&mut headers[..]);
2579
2580 let result = crate::ParserConfig::default()
2581 .parse_request(&mut request, REQUEST);
2582 assert_eq!(result, Err(crate::Error::HeaderValue));
2583
2584 let result = crate::ParserConfig::default()
2585 .ignore_invalid_headers_in_requests(true)
2586 .parse_request(&mut request, REQUEST);
2587 assert_eq!(result, Err(crate::Error::HeaderValue));
2588 }
2589
2590 #[test]
2591 fn test_header_with_invalid_char_in_value() {
2592 const RESPONSE: &[u8] =
2593 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
2594
2595 let mut headers = [EMPTY_HEADER; 2];
2596 let mut response = Response::new(&mut headers[..]);
2597
2598 let result = crate::ParserConfig::default()
2599 .parse_response(&mut response, RESPONSE);
2600 assert_eq!(result, Err(crate::Error::HeaderValue));
2601
2602 let result = crate::ParserConfig::default()
2603 .ignore_invalid_headers_in_responses(true)
2604 .parse_response(&mut response, RESPONSE);
2605 assert_eq!(result, Ok(Status::Complete(78)));
2606
2607 assert_eq!(response.version.unwrap(), 1);
2608 assert_eq!(response.code.unwrap(), 200);
2609 assert_eq!(response.reason.unwrap(), "OK");
2610 assert_eq!(response.headers.len(), 1);
2611 assert_eq!(response.headers[0].name, "Bread");
2612 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2613
2614 const REQUEST: &[u8] =
2615 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
2616
2617 let mut headers = [EMPTY_HEADER; 2];
2618 let mut request = Request::new(&mut headers[..]);
2619
2620 let result = crate::ParserConfig::default()
2621 .parse_request(&mut request, REQUEST);
2622 assert_eq!(result, Err(crate::Error::HeaderValue));
2623
2624 let result = crate::ParserConfig::default()
2625 .ignore_invalid_headers_in_requests(true)
2626 .parse_request(&mut request, REQUEST);
2627 assert_eq!(result, Ok(Status::Complete(77)));
2628
2629 assert_eq!(request.version.unwrap(), 1);
2630 assert_eq!(request.method.unwrap(), "GET");
2631 assert_eq!(request.path.unwrap(), "/");
2632 assert_eq!(request.headers.len(), 1);
2633 assert_eq!(request.headers[0].name, "Bread");
2634 assert_eq!(request.headers[0].value, &b"baguette"[..]);
2635 }
2636
2637 #[test]
2638 fn test_header_with_invalid_char_in_value_with_folding() {
2639 const RESPONSE: &[u8] =
2640 b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o \n world!\r\nBread: baguette\r\n\r\n";
2641
2642 let mut headers = [EMPTY_HEADER; 2];
2643 let mut response = Response::new(&mut headers[..]);
2644
2645 let result = crate::ParserConfig::default()
2646 .parse_response(&mut response, RESPONSE);
2647 assert_eq!(result, Err(crate::Error::HeaderValue));
2648
2649 let result = crate::ParserConfig::default()
2650 .ignore_invalid_headers_in_responses(true)
2651 .parse_response(&mut response, RESPONSE);
2652 assert_eq!(result, Ok(Status::Complete(88)));
2653
2654 assert_eq!(response.version.unwrap(), 1);
2655 assert_eq!(response.code.unwrap(), 200);
2656 assert_eq!(response.reason.unwrap(), "OK");
2657 assert_eq!(response.headers.len(), 1);
2658 assert_eq!(response.headers[0].name, "Bread");
2659 assert_eq!(response.headers[0].value, &b"baguette"[..]);
2660
2661 const REQUEST: &[u8] =
2662 b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o \n world!\r\nBread: baguette\r\n\r\n";
2663
2664 let mut headers = [EMPTY_HEADER; 2];
2665 let mut request = Request::new(&mut headers[..]);
2666
2667 let result = crate::ParserConfig::default()
2668 .parse_request(&mut request, REQUEST);
2669 assert_eq!(result, Err(crate::Error::HeaderValue));
2670
2671 let result = crate::ParserConfig::default()
2672 .ignore_invalid_headers_in_requests(true)
2673 .parse_request(&mut request, REQUEST);
2674 assert_eq!(result, Ok(Status::Complete(87)));
2675
2676 assert_eq!(request.version.unwrap(), 1);
2677 assert_eq!(request.method.unwrap(), "GET");
2678 assert_eq!(request.path.unwrap(), "/");
2679 assert_eq!(request.headers.len(), 1);
2680 assert_eq!(request.headers[0].name, "Bread");
2681 assert_eq!(request.headers[0].value, &b"baguette"[..]);
2682 }
2683
2684 #[test]
2685 fn test_method_within_buffer() {
2686 const REQUEST: &[u8] = b"GET / HTTP/1.1\r\n\r\n";
2687
2688 let mut headers = [EMPTY_HEADER; 0];
2689 let mut request = Request::new(&mut headers[..]);
2690
2691 crate::ParserConfig::default()
2692 .parse_request(&mut request, REQUEST)
2693 .unwrap();
2694
2695 let buf_end = unsafe { REQUEST.as_ptr().add(REQUEST.len()) };
2697 let method = request.method.unwrap();
2699 assert!(REQUEST.as_ptr() <= method.as_ptr());
2700 assert!(method.as_ptr() <= buf_end);
2701 }
2702
2703 static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER: &[u8] =
2704 b"HTTP/1.1 200 OK\r\n Space-Before-Header: hello there\r\n\r\n";
2705
2706 #[test]
2707 fn test_forbid_response_with_space_before_first_header() {
2708 let mut headers = [EMPTY_HEADER; 1];
2709 let mut response = Response::new(&mut headers[..]);
2710 let result = response.parse(RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
2711
2712 assert_eq!(result, Err(crate::Error::HeaderName));
2713 }
2714
2715 #[test]
2716 fn test_allow_response_response_with_space_before_first_header() {
2717 let mut headers = [EMPTY_HEADER; 1];
2718 let mut response = Response::new(&mut headers[..]);
2719 let result = crate::ParserConfig::default()
2720 .allow_space_before_first_header_name(true)
2721 .parse_response(&mut response, RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
2722
2723 assert_eq!(
2724 result,
2725 Ok(Status::Complete(
2726 RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER.len()
2727 ))
2728 );
2729 assert_eq!(response.version.unwrap(), 1);
2730 assert_eq!(response.code.unwrap(), 200);
2731 assert_eq!(response.reason.unwrap(), "OK");
2732 assert_eq!(response.headers.len(), 1);
2733 assert_eq!(response.headers[0].name, "Space-Before-Header");
2734 assert_eq!(response.headers[0].value, &b"hello there"[..]);
2735 }
2736
2737 #[test]
2738 fn test_no_space_after_colon() {
2739 let mut headers = [EMPTY_HEADER; 1];
2740 let mut response = Response::new(&mut headers[..]);
2741 let result = crate::ParserConfig::default()
2742 .parse_response(&mut response, b"HTTP/1.1 200 OK\r\nfoo:bar\r\n\r\n");
2743
2744 assert_eq!(result, Ok(Status::Complete(28)));
2745 assert_eq!(response.version.unwrap(), 1);
2746 assert_eq!(response.code.unwrap(), 200);
2747 assert_eq!(response.reason.unwrap(), "OK");
2748 assert_eq!(response.headers.len(), 1);
2749 assert_eq!(response.headers[0].name, "foo");
2750 assert_eq!(response.headers[0].value, &b"bar"[..]);
2751 }
2752
2753 #[test]
2754 fn test_request_with_leading_space() {
2755 let mut headers = [EMPTY_HEADER; 1];
2756 let mut request = Request::new(&mut headers[..]);
2757 let result = crate::ParserConfig::default()
2758 .parse_request(&mut request, b" GET / HTTP/1.1\r\nfoo:bar\r\n\r\n");
2759
2760 assert_eq!(result, Err(Error::Token));
2761 }
2762
2763 #[test]
2764 fn test_request_with_invalid_method() {
2765 let mut headers = [EMPTY_HEADER; 1];
2766 let mut request = Request::new(&mut headers[..]);
2767 let result = crate::ParserConfig::default()
2768 .parse_request(&mut request, b"P()ST / HTTP/1.1\r\nfoo:bar\r\n\r\n");
2769
2770 assert_eq!(result, Err(Error::Token));
2771 }
2772
2773 #[test]
2774 fn test_utf8_in_path_ok() {
2775 let mut headers = [EMPTY_HEADER; 1];
2776 let mut request = Request::new(&mut headers[..]);
2777
2778 let result = crate::ParserConfig::default().parse_request(&mut request, b"GET /test?post=I\xE2\x80\x99msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n");
2779
2780 assert_eq!(result, Ok(Status::Complete(67)));
2781 assert_eq!(request.version.unwrap(), 1);
2782 assert_eq!(request.method.unwrap(), "GET");
2783 assert_eq!(request.path.unwrap(), "/test?post=I’msorryIforkedyou");
2784 assert_eq!(request.headers.len(), 1);
2785 assert_eq!(request.headers[0].name, "Host");
2786 assert_eq!(request.headers[0].value, &b"example.org"[..]);
2787 }
2788
2789 #[test]
2790 fn test_bad_utf8_in_path() {
2791 let mut headers = [EMPTY_HEADER; 1];
2792 let mut request = Request::new(&mut headers[..]);
2793
2794 let result = crate::ParserConfig::default().parse_request(&mut request, b"GET /test?post=I\xE2msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n");
2795
2796 assert_eq!(result, Err(crate::Error::Token));
2797 }
2798}