@@ -107,22 +107,32 @@ def test_c_parser_loaded():
107
107
108
108
def test_parse_headers (parser : Any ) -> None :
109
109
text = b"""GET /test HTTP/1.1\r
110
- test: line\r
111
- continue\r
110
+ test: a line\r
112
111
test2: data\r
113
112
\r
114
113
"""
115
114
messages , upgrade , tail = parser .feed_data (text )
116
115
assert len (messages ) == 1
117
116
msg = messages [0 ][0 ]
118
117
119
- assert list (msg .headers .items ()) == [("test" , "line continue " ), ("test2" , "data" )]
120
- assert msg .raw_headers == ((b"test" , b"line continue " ), (b"test2" , b"data" ))
118
+ assert list (msg .headers .items ()) == [("test" , "a line " ), ("test2" , "data" )]
119
+ assert msg .raw_headers == ((b"test" , b"a line " ), (b"test2" , b"data" ))
121
120
assert not msg .should_close
122
121
assert msg .compression is None
123
122
assert not msg .upgrade
124
123
125
124
125
+ def test_reject_obsolete_line_folding (parser : Any ) -> None :
126
+ text = b"""GET /test HTTP/1.1\r
127
+ test: line\r
128
+ Content-Length: 48\r
129
+ test2: data\r
130
+ \r
131
+ """
132
+ with pytest .raises (http_exceptions .BadHttpMessage ):
133
+ parser .feed_data (text )
134
+
135
+
126
136
@pytest .mark .skipif (NO_EXTENSIONS , reason = "Only tests C parser." )
127
137
def test_invalid_character (loop : Any , protocol : Any , request : Any ) -> None :
128
138
parser = HttpRequestParserC (
@@ -352,8 +362,8 @@ def test_parse_delayed(parser: Any) -> None:
352
362
353
363
def test_headers_multi_feed (parser : Any ) -> None :
354
364
text1 = b"GET /test HTTP/1.1\r \n "
355
- text2 = b"test: line\r "
356
- text3 = b"\n continue\r \n \r \n "
365
+ text2 = b"test: line"
366
+ text3 = b" continue\r \n \r \n "
357
367
358
368
messages , upgrade , tail = parser .feed_data (text1 )
359
369
assert len (messages ) == 0
@@ -714,31 +724,30 @@ def test_max_header_value_size_under_limit(parser: Any) -> None:
714
724
715
725
716
726
@pytest .mark .parametrize ("size" , [40965 , 8191 ])
717
- def test_max_header_value_size_continuation (parser : Any , size : Any ) -> None :
727
+ def test_max_header_value_size_continuation (response : Any , size : Any ) -> None :
718
728
name = b"T" * (size - 5 )
719
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + name + b"\r \n \r \n "
729
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + name + b"\r \n \r \n "
720
730
721
731
match = f"400, message:\n Got more than 8190 bytes \\ ({ size } \\ ) when reading"
722
732
with pytest .raises (http_exceptions .LineTooLong , match = match ):
723
- parser .feed_data (text )
733
+ response .feed_data (text )
724
734
725
735
726
- def test_max_header_value_size_continuation_under_limit (parser : Any ) -> None :
736
+ def test_max_header_value_size_continuation_under_limit (response : Any ) -> None :
727
737
value = b"A" * 8185
728
- text = b"GET /test HTTP/1.1\r \n " b"data : test\r \n " + value + b"\r \n \r \n "
738
+ text = b"HTTP/1.1 200 Ok \r \n data : test\r \n " + value + b"\r \n \r \n "
729
739
730
- messages , upgrade , tail = parser .feed_data (text )
740
+ messages , upgrade , tail = response .feed_data (text )
731
741
msg = messages [0 ][0 ]
732
- assert msg .method == "GET"
733
- assert msg .path == "/test "
742
+ assert msg .code == 200
743
+ assert msg .reason == "Ok "
734
744
assert msg .version == (1 , 1 )
735
745
assert msg .headers == CIMultiDict ({"data" : "test " + value .decode ()})
736
746
assert msg .raw_headers == ((b"data" , b"test " + value ),)
737
- assert not msg .should_close
747
+ # assert not msg.should_close # TODO: https://github.com/nodejs/llhttp/issues/354
738
748
assert msg .compression is None
739
749
assert not msg .upgrade
740
750
assert not msg .chunked
741
- assert msg .url == URL ("/test" )
742
751
743
752
744
753
def test_http_request_parser (parser : Any ) -> None :
@@ -992,6 +1001,30 @@ def test_http_response_parser_utf8_without_reason(response: Any) -> None:
992
1001
assert not tail
993
1002
994
1003
1004
+ def test_http_response_parser_obs_line_folding (response : Any ) -> None :
1005
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
1006
+
1007
+ messages , upgraded , tail = response .feed_data (text )
1008
+ assert len (messages ) == 1
1009
+ msg = messages [0 ][0 ]
1010
+
1011
+ assert msg .version == (1 , 1 )
1012
+ assert msg .code == 200
1013
+ assert msg .reason == "Ok"
1014
+ assert msg .headers == CIMultiDict ([("TEST" , "line continue" )])
1015
+ assert msg .raw_headers == ((b"test" , b"line continue" ),)
1016
+ assert not upgraded
1017
+ assert not tail
1018
+
1019
+
1020
+ @pytest .mark .dev_mode
1021
+ def test_http_response_parser_strict_obs_line_folding (response : Any ) -> None :
1022
+ text = b"HTTP/1.1 200 Ok\r \n test: line\r \n continue\r \n \r \n "
1023
+
1024
+ with pytest .raises (http_exceptions .BadHttpMessage ):
1025
+ response .feed_data (text )
1026
+
1027
+
995
1028
@pytest .mark .parametrize ("size" , [40962 , 8191 ])
996
1029
def test_http_response_parser_bad_status_line_too_long (
997
1030
response : Any , size : Any
0 commit comments