@@ -38,7 +38,10 @@ def protocol():
38
38
@pytest .fixture (params = REQUEST_PARSERS )
39
39
def parser (loop , protocol , request ):
40
40
"""Parser implementations"""
41
- return request .param (protocol , loop , 8190 , 32768 , 8190 )
41
+ return request .param (protocol , loop ,
42
+ max_line_size = 8190 ,
43
+ max_headers = 32768 ,
44
+ max_field_size = 8190 )
42
45
43
46
44
47
@pytest .fixture (params = REQUEST_PARSERS )
@@ -50,7 +53,10 @@ def request_cls(request):
50
53
@pytest .fixture (params = RESPONSE_PARSERS )
51
54
def response (loop , protocol , request ):
52
55
"""Parser implementations"""
53
- return request .param (protocol , loop , 8190 , 32768 , 8190 )
56
+ return request .param (protocol , loop ,
57
+ max_line_size = 8190 ,
58
+ max_headers = 32768 ,
59
+ max_field_size = 8190 )
54
60
55
61
56
62
@pytest .fixture (params = RESPONSE_PARSERS )
@@ -358,32 +364,82 @@ def test_invalid_name(parser):
358
364
parser .feed_data (text )
359
365
360
366
361
- def test_max_header_field_size (parser ):
362
- name = b'test' * 10 * 1024
367
+ @pytest .mark .parametrize ('size' , [40960 , 8191 ])
368
+ def test_max_header_field_size (parser , size ):
369
+ name = b't' * size
363
370
text = (b'GET /test HTTP/1.1\r \n ' + name + b':data\r \n \r \n ' )
364
371
365
- with pytest .raises (http_exceptions .LineTooLong ):
372
+ match = ("400, message='Got more than 8190 bytes \({}\) when reading"
373
+ .format (size ))
374
+ with pytest .raises (http_exceptions .LineTooLong , match = match ):
366
375
parser .feed_data (text )
367
376
368
377
369
- def test_max_header_value_size (parser ):
370
- name = b'test' * 10 * 1024
378
+ def test_max_header_field_size_under_limit (parser ):
379
+ name = b't' * 8190
380
+ text = (b'GET /test HTTP/1.1\r \n ' + name + b':data\r \n \r \n ' )
381
+
382
+ messages , upgrade , tail = parser .feed_data (text )
383
+ msg = messages [0 ][0 ]
384
+ assert msg == (
385
+ 'GET' , '/test' , (1 , 1 ),
386
+ CIMultiDict ({name .decode (): 'data' }),
387
+ ((name , b'data' ),),
388
+ False , None , False , False , URL ('/test' ))
389
+
390
+
391
+ @pytest .mark .parametrize ('size' , [40960 , 8191 ])
392
+ def test_max_header_value_size (parser , size ):
393
+ name = b't' * size
371
394
text = (b'GET /test HTTP/1.1\r \n '
372
395
b'data:' + name + b'\r \n \r \n ' )
373
396
374
- with pytest .raises (http_exceptions .LineTooLong ):
397
+ match = ("400, message='Got more than 8190 bytes \({}\) when reading"
398
+ .format (size ))
399
+ with pytest .raises (http_exceptions .LineTooLong , match = match ):
375
400
parser .feed_data (text )
376
401
377
402
378
- def test_max_header_value_size_continuation (parser ):
379
- name = b'test' * 10 * 1024
403
+ def test_max_header_value_size_under_limit (parser ):
404
+ value = b'A' * 8190
405
+ text = (b'GET /test HTTP/1.1\r \n '
406
+ b'data:' + value + b'\r \n \r \n ' )
407
+
408
+ messages , upgrade , tail = parser .feed_data (text )
409
+ msg = messages [0 ][0 ]
410
+ assert msg == (
411
+ 'GET' , '/test' , (1 , 1 ),
412
+ CIMultiDict ({'data' : value .decode ()}),
413
+ ((b'data' , value ),),
414
+ False , None , False , False , URL ('/test' ))
415
+
416
+
417
+ @pytest .mark .parametrize ('size' , [40965 , 8191 ])
418
+ def test_max_header_value_size_continuation (parser , size ):
419
+ name = b'T' * (size - 5 )
380
420
text = (b'GET /test HTTP/1.1\r \n '
381
421
b'data: test\r \n ' + name + b'\r \n \r \n ' )
382
422
383
- with pytest .raises (http_exceptions .LineTooLong ):
423
+ match = ("400, message='Got more than 8190 bytes \({}\) when reading"
424
+ .format (size ))
425
+ with pytest .raises (http_exceptions .LineTooLong , match = match ):
384
426
parser .feed_data (text )
385
427
386
428
429
+ def test_max_header_value_size_continuation_under_limit (parser ):
430
+ value = b'A' * 8185
431
+ text = (b'GET /test HTTP/1.1\r \n '
432
+ b'data: test\r \n ' + value + b'\r \n \r \n ' )
433
+
434
+ messages , upgrade , tail = parser .feed_data (text )
435
+ msg = messages [0 ][0 ]
436
+ assert msg == (
437
+ 'GET' , '/test' , (1 , 1 ),
438
+ CIMultiDict ({'data' : 'test ' + value .decode ()}),
439
+ ((b'data' , b'test ' + value ),),
440
+ False , None , False , False , URL ('/test' ))
441
+
442
+
387
443
def test_http_request_parser (parser ):
388
444
text = b'GET /path HTTP/1.1\r \n \r \n '
389
445
messages , upgrade , tail = parser .feed_data (text )
@@ -452,10 +508,23 @@ def test_http_request_parser_bad_version(parser):
452
508
parser .feed_data (b'GET //get HT/11\r \n \r \n ' )
453
509
454
510
455
- def test_http_request_max_status_line (parser ):
456
- with pytest .raises (http_exceptions .LineTooLong ):
511
+ @pytest .mark .parametrize ('size' , [40965 , 8191 ])
512
+ def test_http_request_max_status_line (parser , size ):
513
+ path = b't' * (size - 5 )
514
+ match = ("400, message='Got more than 8190 bytes \({}\) when reading"
515
+ .format (size ))
516
+ with pytest .raises (http_exceptions .LineTooLong , match = match ):
457
517
parser .feed_data (
458
- b'GET /path' + b'test' * 10 * 1024 + b' HTTP/1.1\r \n \r \n ' )
518
+ b'GET /path' + path + b' HTTP/1.1\r \n \r \n ' )
519
+
520
+
521
+ def test_http_request_max_status_line_under_limit (parser ):
522
+ path = b't' * (8190 - 5 )
523
+ messages , upgraded , tail = parser .feed_data (
524
+ b'GET /path' + path + b' HTTP/1.1\r \n \r \n ' )
525
+ msg = messages [0 ][0 ]
526
+ assert msg == ('GET' , '/path' + path .decode (), (1 , 1 ), CIMultiDict (), (),
527
+ False , None , False , False , URL ('/path' + path .decode ()))
459
528
460
529
461
530
def test_http_response_parser_utf8 (response ):
@@ -474,10 +543,24 @@ def test_http_response_parser_utf8(response):
474
543
assert not tail
475
544
476
545
477
- def test_http_response_parser_bad_status_line_too_long (response ):
478
- with pytest .raises (http_exceptions .LineTooLong ):
546
+ @pytest .mark .parametrize ('size' , [40962 , 8191 ])
547
+ def test_http_response_parser_bad_status_line_too_long (response , size ):
548
+ reason = b't' * (size - 2 )
549
+ match = ("400, message='Got more than 8190 bytes \({}\) when reading"
550
+ .format (size ))
551
+ with pytest .raises (http_exceptions .LineTooLong , match = match ):
479
552
response .feed_data (
480
- b'HTTP/1.1 200 Ok' + b'test' * 10 * 1024 + b'\r \n \r \n ' )
553
+ b'HTTP/1.1 200 Ok' + reason + b'\r \n \r \n ' )
554
+
555
+
556
+ def test_http_response_parser_status_line_under_limit (response ):
557
+ reason = b'O' * 8190
558
+ messages , upgraded , tail = response .feed_data (
559
+ b'HTTP/1.1 200 ' + reason + b'\r \n \r \n ' )
560
+ msg = messages [0 ][0 ]
561
+ assert msg .version == (1 , 1 )
562
+ assert msg .code == 200
563
+ assert msg .reason == reason .decode ()
481
564
482
565
483
566
def test_http_response_parser_bad_version (response ):
0 commit comments