@@ -247,10 +247,11 @@ pub struct ParserConfig {
247
247
allow_obsolete_multiline_headers_in_responses : bool ,
248
248
allow_multiple_spaces_in_request_line_delimiters : bool ,
249
249
allow_multiple_spaces_in_response_status_delimiters : bool ,
250
+ ignore_invalid_header_lines_in_responses : bool ,
250
251
}
251
252
252
253
impl 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 .
254
255
pub fn allow_spaces_after_header_name_in_responses (
255
256
& mut self ,
256
257
value : bool ,
@@ -361,6 +362,15 @@ impl ParserConfig {
361
362
request. parse_with_config_and_uninit_headers ( buf, self , headers)
362
363
}
363
364
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
+
364
374
/// Parses a response with the given config.
365
375
pub fn parse_response < ' headers , ' buf > (
366
376
& self ,
@@ -935,11 +945,6 @@ fn parse_headers_iter_uninit<'a, 'b>(
935
945
return Err ( Error :: HeaderName ) ;
936
946
}
937
947
938
- let uninit_header = match iter. next ( ) {
939
- Some ( header) => header,
940
- None => break ' headers
941
- } ;
942
-
943
948
// parse header name until colon
944
949
let header_name: & str = ' name: loop {
945
950
let mut b = next ! ( bytes) ;
@@ -969,7 +974,23 @@ fn parse_headers_iter_uninit<'a, 'b>(
969
974
}
970
975
}
971
976
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
973
994
} ;
974
995
975
996
let mut b;
@@ -1629,6 +1650,23 @@ mod tests {
1629
1650
assert_eq ! ( response. headers[ 1 ] . value, & b"baguette" [ ..] ) ;
1630
1651
}
1631
1652
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
+
1632
1670
static REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON : & ' static [ u8 ] =
1633
1671
b"GET / HTTP/1.1\r \n Host : localhost\r \n \r \n " ;
1634
1672
@@ -1914,4 +1952,63 @@ mod tests {
1914
1952
1915
1953
assert_eq ! ( result, Err ( :: Error :: HeaderName ) ) ;
1916
1954
}
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
+
1917
2014
}
0 commit comments