@@ -108,22 +108,32 @@ def test_c_parser_loaded():
108
108
109
109
def test_parse_headers (parser : Any ) -> None :
110
110
text = b"""GET /test HTTP/1.1\r
111
- test: line\r
112
- continue\r
111
+ test: a line\r
113
112
test2: data\r
114
113
\r
115
114
"""
116
115
messages , upgrade , tail = parser .feed_data (text )
117
116
assert len (messages ) == 1
118
117
msg = messages [0 ][0 ]
119
118
120
- assert list (msg .headers .items ()) == [("test" , "line continue " ), ("test2" , "data" )]
121
- assert msg .raw_headers == ((b"test" , b"line continue " ), (b"test2" , b"data" ))
119
+ assert list (msg .headers .items ()) == [("test" , "a line " ), ("test2" , "data" )]
120
+ assert msg .raw_headers == ((b"test" , b"a line " ), (b"test2" , b"data" ))
122
121
assert not msg .should_close
123
122
assert msg .compression is None
124
123
assert not msg .upgrade
125
124
126
125
126
+ def test_reject_obsolete_line_folding (parser : Any ) -> None :
127
+ text = b"""GET /test HTTP/1.1\r
128
+ test: line\r
129
+ Content-Length: 48\r
130
+ test2: data\r
131
+ \r
132
+ """
133
+ with pytest .raises (http_exceptions .BadHttpMessage ):
134
+ parser .feed_data (text )
135
+
136
+
127
137
@pytest .mark .skipif (NO_EXTENSIONS , reason = "Only tests C parser." )
128
138
def test_invalid_character (loop : Any , protocol : Any , request : Any ) -> None :
129
139
parser = HttpRequestParserC (
@@ -342,8 +352,8 @@ def test_parse_delayed(parser) -> None:
342
352
343
353
def test_headers_multi_feed (parser ) -> None :
344
354
text1 = b"GET /test HTTP/1.1\r \n "
345
- text2 = b"test: line\r "
346
- text3 = b"\n continue\r \n \r \n "
355
+ text2 = b"test: line"
356
+ text3 = b" continue\r \n \r \n "
347
357
348
358
messages , upgrade , tail = parser .feed_data (text1 )
349
359
assert len (messages ) == 0
@@ -705,31 +715,30 @@ def test_max_header_value_size_under_limit(parser) -> None:
705
715
706
716
707
717
@pytest .mark .parametrize ("size" , [40965 , 8191 ])
708
- def test_max_header_value_size_continuation (parser , size ) -> None :
718
+ def test_max_header_value_size_continuation (response , size ) -> None :
709
719
name = b"T" * (size - 5 )
710
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + name + b"\r \n \r \n "
720
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + name + b"\r \n \r \n "
711
721
712
722
match = f"400, message:\n Got more than 8190 bytes \\ ({ size } \\ ) when reading"
713
723
with pytest .raises (http_exceptions .LineTooLong , match = match ):
714
- parser .feed_data (text )
724
+ response .feed_data (text )
715
725
716
726
717
- def test_max_header_value_size_continuation_under_limit (parser ) -> None :
727
+ def test_max_header_value_size_continuation_under_limit (response ) -> None :
718
728
value = b"A" * 8185
719
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + value + b"\r \n \r \n "
729
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + value + b"\r \n \r \n "
720
730
721
- messages , upgrade , tail = parser .feed_data (text )
731
+ messages , upgrade , tail = response .feed_data (text )
722
732
msg = messages [0 ][0 ]
723
- assert msg .method == "GET"
724
- assert msg .path == "/test "
733
+ assert msg .code == 200
734
+ assert msg .reason == "Ok "
725
735
assert msg .version == (1 , 1 )
726
736
assert msg .headers == CIMultiDict ({"data" : "test " + value .decode ()})
727
737
assert msg .raw_headers == ((b"data" , b"test " + value ),)
728
- assert not msg .should_close
738
+ # assert not msg.should_close # TODO: https://github.com/nodejs/llhttp/issues/354
729
739
assert msg .compression is None
730
740
assert not msg .upgrade
731
741
assert not msg .chunked
732
- assert msg .url == URL ("/test" )
733
742
734
743
735
744
def test_http_request_parser (parser ) -> None :
@@ -970,6 +979,30 @@ def test_http_response_parser_utf8_without_reason(response: Any) -> None:
970
979
assert not tail
971
980
972
981
982
+ def test_http_response_parser_obs_line_folding (response : Any ) -> None :
983
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
984
+
985
+ messages , upgraded , tail = response .feed_data (text )
986
+ assert len (messages ) == 1
987
+ msg = messages [0 ][0 ]
988
+
989
+ assert msg .version == (1 , 1 )
990
+ assert msg .code == 200
991
+ assert msg .reason == "Ok"
992
+ assert msg .headers == CIMultiDict ([("TEST" , "line continue" )])
993
+ assert msg .raw_headers == ((b"test" , b"line continue" ),)
994
+ assert not upgraded
995
+ assert not tail
996
+
997
+
998
+ @pytest .mark .dev_mode
999
+ def test_http_response_parser_strict_obs_line_folding (response : Any ) -> None :
1000
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
1001
+
1002
+ with pytest .raises (http_exceptions .BadHttpMessage ):
1003
+ response .feed_data (text )
1004
+
1005
+
973
1006
@pytest .mark .parametrize ("size" , [40962 , 8191 ])
974
1007
def test_http_response_parser_bad_status_line_too_long (response , size ) -> None :
975
1008
reason = b"t" * (size - 2 )
0 commit comments