diff options
author | Bert JW Regeer <bertjw@regeer.org> | 2019-12-12 20:01:41 -0800 |
---|---|---|
committer | Bert JW Regeer <bertjw@regeer.org> | 2019-12-19 15:59:58 +0100 |
commit | 60f92b822538230f279efcfb9561dd2c2524d696 (patch) | |
tree | e65f24486503218c7d255af4f98264d294e2d7b6 | |
parent | 8ecd8dc4be000a0e1be2212dc35ea6a418a8523e (diff) | |
download | waitress-60f92b822538230f279efcfb9561dd2c2524d696.tar.gz |
Allow end of chunk parser to be resumeable
-rw-r--r-- | waitress/receiver.py | 26 | ||||
-rw-r--r-- | waitress/tests/test_receiver.py | 27 |
2 files changed, 44 insertions, 9 deletions
diff --git a/waitress/receiver.py b/waitress/receiver.py index 693c7d5..5d1568d 100644 --- a/waitress/receiver.py +++ b/waitress/receiver.py @@ -64,6 +64,7 @@ class ChunkedReceiver(object): chunk_remainder = 0 validate_chunk_end = False control_line = b"" + chunk_end = b"" all_chunks_received = False trailer = b"" completed = False @@ -100,17 +101,24 @@ class ChunkedReceiver(object): if self.chunk_remainder == 0: self.validate_chunk_end = True elif self.validate_chunk_end: + s = self.chunk_end + s + pos = s.find(b"\r\n") - if pos == 0: - # Chop off the terminating CR LF from the chunk - s = s[2:] + if pos < 0 and len(s) < 2: + self.chunk_end = s + s = b"" else: - self.error = BadRequest("Chunk not properly terminated") - self.all_chunks_received = True - - # Always exit this loop - self.validate_chunk_end = False + self.chunk_end = b"" + if pos == 0: + # Chop off the terminating CR LF from the chunk + s = s[2:] + else: + self.error = BadRequest("Chunk not properly terminated") + self.all_chunks_received = True + + # Always exit this loop + self.validate_chunk_end = False elif not self.all_chunks_received: # Receive a control line. s = self.control_line + s @@ -119,7 +127,7 @@ class ChunkedReceiver(object): if pos < 0: # Control line not finished. self.control_line = s - s = "" + s = b"" else: # Control line finished. line = s[:pos] diff --git a/waitress/tests/test_receiver.py b/waitress/tests/test_receiver.py index 92b66ad..b4910bb 100644 --- a/waitress/tests/test_receiver.py +++ b/waitress/tests/test_receiver.py @@ -198,6 +198,33 @@ class TestChunkedReceiver(unittest.TestCase): self.assertEqual(b"".join(buf.data), b"Wikipedia in\r\n\r\nchunks.") self.assertEqual(inst.error, None) + def test_received_multiple_chunks_split(self): + from waitress.utilities import BadRequest + + buf = DummyBuffer() + inst = self._makeOne(buf) + data1 = b"4\r\nWiki\r" + result = inst.received(data1) + self.assertEqual(result, len(data1)) + + data2 = ( + b"\n5\r\n" + b"pedia\r\n" + b"E\r\n" + b" in\r\n" + b"\r\n" + b"chunks.\r\n" + b"0\r\n" + b"\r\n" + ) + + result = inst.received(data2) + self.assertEqual(result, len(data2)) + + self.assertEqual(inst.completed, True) + self.assertEqual(b"".join(buf.data), b"Wikipedia in\r\n\r\nchunks.") + self.assertEqual(inst.error, None) + class DummyBuffer(object): def __init__(self, data=None): |