@@ -247,10 +247,11 @@ pub struct ParserConfig {
247247 allow_obsolete_multiline_headers_in_responses : bool ,
248248 allow_multiple_spaces_in_request_line_delimiters : bool ,
249249 allow_multiple_spaces_in_response_status_delimiters : bool ,
250+ ignore_invalid_header_lines_in_responses : bool ,
250251}
251252
252253impl ParserConfig {
253- /// Sets whether spaces should be allowed after header name .
254+ /// Sets whether spaces and tabs should be allowed after header names in responses .
254255 pub fn allow_spaces_after_header_name_in_responses (
255256 & mut self ,
256257 value : bool ,
@@ -361,6 +362,15 @@ impl ParserConfig {
361362 request. parse_with_config_and_uninit_headers ( buf, self , headers)
362363 }
363364
365+ /// Sets whether invalid header lines should be silently ignored in responses.
366+ pub fn ignore_invalid_header_lines_in_responses (
367+ & mut self ,
368+ value : bool ,
369+ ) -> & mut Self {
370+ self . ignore_invalid_header_lines_in_responses = value;
371+ self
372+ }
373+
364374 /// Parses a response with the given config.
365375 pub fn parse_response < ' headers , ' buf > (
366376 & self ,
@@ -935,11 +945,6 @@ fn parse_headers_iter_uninit<'a, 'b>(
935945 return Err ( Error :: HeaderName ) ;
936946 }
937947
938- let uninit_header = match iter. next ( ) {
939- Some ( header) => header,
940- None => break ' headers
941- } ;
942-
943948 // parse header name until colon
944949 let header_name: & str = ' name: loop {
945950 let mut b = next ! ( bytes) ;
@@ -969,7 +974,23 @@ fn parse_headers_iter_uninit<'a, 'b>(
969974 }
970975 }
971976
972- return Err ( Error :: HeaderName ) ;
977+ if !config. ignore_invalid_header_lines_in_responses {
978+ return Err ( Error :: HeaderName ) ;
979+ }
980+
981+ while b != b'\n' {
982+ b = next ! ( bytes) ;
983+ }
984+
985+ count += bytes. pos ( ) ;
986+ bytes. slice ( ) ;
987+
988+ continue ' headers;
989+ } ;
990+
991+ let uninit_header = match iter. next ( ) {
992+ Some ( header) => header,
993+ None => break ' headers
973994 } ;
974995
975996 let mut b;
@@ -1629,6 +1650,23 @@ mod tests {
16291650 assert_eq ! ( response. headers[ 1 ] . value, & b"baguette" [ ..] ) ;
16301651 }
16311652
1653+ #[ test]
1654+ fn test_ignore_header_line_with_whitespaces_after_header_name ( ) {
1655+ let mut headers = [ EMPTY_HEADER ; 2 ] ;
1656+ let mut response = Response :: new ( & mut headers[ ..] ) ;
1657+ let result = :: ParserConfig :: default ( )
1658+ . ignore_invalid_header_lines_in_responses ( true )
1659+ . parse_response ( & mut response, RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON ) ;
1660+
1661+ assert_eq ! ( result, Ok ( Status :: Complete ( 77 ) ) ) ;
1662+ assert_eq ! ( response. version. unwrap( ) , 1 ) ;
1663+ assert_eq ! ( response. code. unwrap( ) , 200 ) ;
1664+ assert_eq ! ( response. reason. unwrap( ) , "OK" ) ;
1665+ assert_eq ! ( response. headers. len( ) , 1 ) ;
1666+ assert_eq ! ( response. headers[ 0 ] . name, "Bread" ) ;
1667+ assert_eq ! ( response. headers[ 0 ] . value, & b"baguette" [ ..] ) ;
1668+ }
1669+
16321670 static REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON : & ' static [ u8 ] =
16331671 b"GET / HTTP/1.1\r \n Host : localhost\r \n \r \n " ;
16341672
@@ -1914,4 +1952,63 @@ mod tests {
19141952
19151953 assert_eq ! ( result, Err ( :: Error :: HeaderName ) ) ;
19161954 }
1955+
1956+ #[ test]
1957+ fn test_ignore_header_line_with_invalid_char_after_header_name ( ) {
1958+ let mut headers = [ EMPTY_HEADER ; 2 ] ;
1959+ let mut response = Response :: new ( & mut headers[ ..] ) ;
1960+ let result = :: ParserConfig :: default ( )
1961+ . ignore_invalid_header_lines_in_responses ( true )
1962+ . parse_response ( & mut response, RESPONSE_WITH_INVALID_CHAR_BETWEEN_HEADER_NAME_AND_COLON ) ;
1963+
1964+ assert_eq ! ( result, Ok ( Status :: Complete ( 77 ) ) ) ;
1965+ assert_eq ! ( response. version. unwrap( ) , 1 ) ;
1966+ assert_eq ! ( response. code. unwrap( ) , 200 ) ;
1967+ assert_eq ! ( response. reason. unwrap( ) , "OK" ) ;
1968+ assert_eq ! ( response. headers. len( ) , 1 ) ;
1969+ assert_eq ! ( response. headers[ 0 ] . name, "Bread" ) ;
1970+ assert_eq ! ( response. headers[ 0 ] . value, & b"baguette" [ ..] ) ;
1971+ }
1972+
1973+ static RESPONSE_WITH_MISSING_COLON : & ' static [ u8 ] =
1974+ b"HTTP/1.1 200 OK\r \n Access-Control-Allow-Credentials\r \n Bread: baguette\r \n \r \n " ;
1975+
1976+ #[ test]
1977+ fn test_ignore_header_line_with_missing_colon ( ) {
1978+ let mut headers = [ EMPTY_HEADER ; 2 ] ;
1979+ let mut response = Response :: new ( & mut headers[ ..] ) ;
1980+ let result = :: ParserConfig :: default ( )
1981+ . ignore_invalid_header_lines_in_responses ( true )
1982+ . parse_response ( & mut response, RESPONSE_WITH_MISSING_COLON ) ;
1983+
1984+ assert_eq ! ( result, Ok ( Status :: Complete ( 70 ) ) ) ;
1985+ assert_eq ! ( response. version. unwrap( ) , 1 ) ;
1986+ assert_eq ! ( response. code. unwrap( ) , 200 ) ;
1987+ assert_eq ! ( response. reason. unwrap( ) , "OK" ) ;
1988+ assert_eq ! ( response. headers. len( ) , 1 ) ;
1989+ assert_eq ! ( response. headers[ 0 ] . name, "Bread" ) ;
1990+ assert_eq ! ( response. headers[ 0 ] . value, & b"baguette" [ ..] ) ;
1991+ }
1992+
1993+ static RESPONSE_WITH_INVALID_CHAR_AFTER_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON : & ' static [ u8 ] =
1994+ b"HTTP/1.1 200 OK\r \n Access-Control-Allow-Credentials \xFF : true\r \n Bread: baguette\r \n \r \n " ;
1995+
1996+ #[ test]
1997+ fn test_ignore_header_line_with_invalid_char_after_whitespace ( ) {
1998+ let mut headers = [ EMPTY_HEADER ; 2 ] ;
1999+ let mut response = Response :: new ( & mut headers[ ..] ) ;
2000+ let result = :: ParserConfig :: default ( )
2001+ . allow_spaces_after_header_name_in_responses ( true )
2002+ . ignore_invalid_header_lines_in_responses ( true )
2003+ . parse_response ( & mut response, RESPONSE_WITH_INVALID_CHAR_AFTER_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON ) ;
2004+
2005+ assert_eq ! ( result, Ok ( Status :: Complete ( 81 ) ) ) ;
2006+ assert_eq ! ( response. version. unwrap( ) , 1 ) ;
2007+ assert_eq ! ( response. code. unwrap( ) , 200 ) ;
2008+ assert_eq ! ( response. reason. unwrap( ) , "OK" ) ;
2009+ assert_eq ! ( response. headers. len( ) , 1 ) ;
2010+ assert_eq ! ( response. headers[ 0 ] . name, "Bread" ) ;
2011+ assert_eq ! ( response. headers[ 0 ] . value, & b"baguette" [ ..] ) ;
2012+ }
2013+
19172014}
0 commit comments