@@ -419,6 +419,110 @@ def test_parser_request_4(self):
419
419
with self .assertRaisesRegex (TypeError , 'a bytes-like object' ):
420
420
p .feed_data ('POST HTTP/1.2' )
421
421
422
+ def test_parser_request_fragmented (self ):
423
+ m = mock .Mock ()
424
+ headers = {}
425
+ m .on_header .side_effect = headers .__setitem__
426
+ p = httptools .HttpRequestParser (m )
427
+
428
+ REQUEST = (
429
+ b'PUT / HTTP/1.1\r \n Host: localhost:1234\r \n Content-Type: text/pl' ,
430
+ b'ain; charset=utf-8\r \n X-Empty-Header: \r \n Connection: close\r \n ' ,
431
+ b'Content-Length: 10\r \n \r \n 1234567890' ,
432
+ )
433
+
434
+ p .feed_data (REQUEST [0 ])
435
+
436
+ m .on_message_begin .assert_called_once_with ()
437
+ m .on_url .assert_called_once_with (b'/' )
438
+ self .assertEqual (headers , {b'Host' : b'localhost:1234' })
439
+
440
+ p .feed_data (REQUEST [1 ])
441
+ self .assertEqual (
442
+ headers ,
443
+ {b'Host' : b'localhost:1234' ,
444
+ b'Content-Type' : b'text/plain; charset=utf-8' ,
445
+ b'X-Empty-Header' : b'' })
446
+
447
+ p .feed_data (REQUEST [2 ])
448
+ self .assertEqual (
449
+ headers ,
450
+ {b'Host' : b'localhost:1234' ,
451
+ b'Content-Type' : b'text/plain; charset=utf-8' ,
452
+ b'X-Empty-Header' : b'' ,
453
+ b'Connection' : b'close' ,
454
+ b'Content-Length' : b'10' })
455
+ m .on_message_complete .assert_called_once_with ()
456
+
457
+ def test_parser_request_fragmented_header (self ):
458
+ m = mock .Mock ()
459
+ headers = {}
460
+ m .on_header .side_effect = headers .__setitem__
461
+ p = httptools .HttpRequestParser (m )
462
+
463
+ REQUEST = (
464
+ b'PUT / HTTP/1.1\r \n Host: localhost:1234\r \n Content-' ,
465
+ b'Type: text/plain; charset=utf-8\r \n \r \n ' ,
466
+ )
467
+
468
+ p .feed_data (REQUEST [0 ])
469
+
470
+ m .on_message_begin .assert_called_once_with ()
471
+ m .on_url .assert_called_once_with (b'/' )
472
+ self .assertEqual (headers , {b'Host' : b'localhost:1234' })
473
+
474
+ p .feed_data (REQUEST [1 ])
475
+ self .assertEqual (
476
+ headers ,
477
+ {b'Host' : b'localhost:1234' ,
478
+ b'Content-Type' : b'text/plain; charset=utf-8' })
479
+
480
+ def test_parser_request_fragmented_value (self ):
481
+ m = mock .Mock ()
482
+ headers = {}
483
+ m .on_header .side_effect = headers .__setitem__
484
+ p = httptools .HttpRequestParser (m )
485
+
486
+ REQUEST = (
487
+ b'PUT / HTTP/1.1\r \n Host: localhost:1234\r \n Content-Type:' ,
488
+ b' text/pla' ,
489
+ b'in; chars' ,
490
+ b'et=utf-8\r \n \r \n ' ,
491
+ )
492
+
493
+ p .feed_data (REQUEST [0 ])
494
+
495
+ m .on_message_begin .assert_called_once_with ()
496
+ m .on_url .assert_called_once_with (b'/' )
497
+ self .assertEqual (headers , {b'Host' : b'localhost:1234' })
498
+
499
+ p .feed_data (REQUEST [1 ])
500
+ p .feed_data (REQUEST [2 ])
501
+ p .feed_data (REQUEST [3 ])
502
+ self .assertEqual (
503
+ headers ,
504
+ {b'Host' : b'localhost:1234' ,
505
+ b'Content-Type' : b'text/plain; charset=utf-8' })
506
+
507
+ def test_parser_request_fragmented_bytes (self ):
508
+ m = mock .Mock ()
509
+ headers = {}
510
+ m .on_header .side_effect = headers .__setitem__
511
+ p = httptools .HttpRequestParser (m )
512
+
513
+ REQUEST = \
514
+ b'PUT / HTTP/1.1\r \n Host: localhost:1234\r \n Content-' \
515
+ b'Type: text/plain; charset=utf-8\r \n \r \n '
516
+
517
+ step = 1
518
+ for i in range (0 , len (REQUEST ), step ):
519
+ p .feed_data (REQUEST [i :i + step ])
520
+
521
+ self .assertEqual (
522
+ headers ,
523
+ {b'Host' : b'localhost:1234' ,
524
+ b'Content-Type' : b'text/plain; charset=utf-8' })
525
+
422
526
423
527
class TestUrlParser (unittest .TestCase ):
424
528
0 commit comments