@@ -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 (
@@ -353,8 +363,8 @@ def test_parse_delayed(parser) -> None:
353
363
354
364
def test_headers_multi_feed (parser ) -> None :
355
365
text1 = b"GET /test HTTP/1.1\r \n "
356
- text2 = b"test: line\r "
357
- text3 = b"\n continue\r \n \r \n "
366
+ text2 = b"test: line"
367
+ text3 = b" continue\r \n \r \n "
358
368
359
369
messages , upgrade , tail = parser .feed_data (text1 )
360
370
assert len (messages ) == 0
@@ -713,31 +723,30 @@ def test_max_header_value_size_under_limit(parser) -> None:
713
723
714
724
715
725
@pytest .mark .parametrize ("size" , [40965 , 8191 ])
716
- def test_max_header_value_size_continuation (parser , size ) -> None :
726
+ def test_max_header_value_size_continuation (response , size ) -> None :
717
727
name = b"T" * (size - 5 )
718
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + name + b"\r \n \r \n "
728
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + name + b"\r \n \r \n "
719
729
720
730
match = f"400, message:\n Got more than 8190 bytes \\ ({ size } \\ ) when reading"
721
731
with pytest .raises (http_exceptions .LineTooLong , match = match ):
722
- parser .feed_data (text )
732
+ response .feed_data (text )
723
733
724
734
725
- def test_max_header_value_size_continuation_under_limit (parser ) -> None :
735
+ def test_max_header_value_size_continuation_under_limit (response ) -> None :
726
736
value = b"A" * 8185
727
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + value + b"\r \n \r \n "
737
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + value + b"\r \n \r \n "
728
738
729
- messages , upgrade , tail = parser .feed_data (text )
739
+ messages , upgrade , tail = response .feed_data (text )
730
740
msg = messages [0 ][0 ]
731
- assert msg .method == "GET"
732
- assert msg .path == "/test "
741
+ assert msg .code == 200
742
+ assert msg .reason == "Ok "
733
743
assert msg .version == (1 , 1 )
734
744
assert msg .headers == CIMultiDict ({"data" : "test " + value .decode ()})
735
745
assert msg .raw_headers == ((b"data" , b"test " + value ),)
736
- assert not msg .should_close
746
+ # assert not msg.should_close # TODO: https://github.com/nodejs/llhttp/issues/354
737
747
assert msg .compression is None
738
748
assert not msg .upgrade
739
749
assert not msg .chunked
740
- assert msg .url == URL ("/test" )
741
750
742
751
743
752
def test_http_request_parser (parser ) -> None :
@@ -991,6 +1000,30 @@ def test_http_response_parser_utf8_without_reason(response: Any) -> None:
991
1000
assert not tail
992
1001
993
1002
1003
+ def test_http_response_parser_obs_line_folding (response : Any ) -> None :
1004
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
1005
+
1006
+ messages , upgraded , tail = response .feed_data (text )
1007
+ assert len (messages ) == 1
1008
+ msg = messages [0 ][0 ]
1009
+
1010
+ assert msg .version == (1 , 1 )
1011
+ assert msg .code == 200
1012
+ assert msg .reason == "Ok"
1013
+ assert msg .headers == CIMultiDict ([("TEST" , "line continue" )])
1014
+ assert msg .raw_headers == ((b"test" , b"line continue" ),)
1015
+ assert not upgraded
1016
+ assert not tail
1017
+
1018
+
1019
+ @pytest .mark .dev_mode
1020
+ def test_http_response_parser_strict_obs_line_folding (response : Any ) -> None :
1021
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
1022
+
1023
+ with pytest .raises (http_exceptions .BadHttpMessage ):
1024
+ response .feed_data (text )
1025
+
1026
+
994
1027
@pytest .mark .parametrize ("size" , [40962 , 8191 ])
995
1028
def test_http_response_parser_bad_status_line_too_long (response , size ) -> None :
996
1029
reason = b"t" * (size - 2 )
0 commit comments