diff --git a/aiohttp/multipart.py b/aiohttp/multipart.py index e3ea335bf48..d87920634ab 100644 --- a/aiohttp/multipart.py +++ b/aiohttp/multipart.py @@ -247,7 +247,7 @@ def read_chunk(self, size=chunk_size): 'Content-Length required for chunked read' chunk_size = min(size, self._length - self._read_bytes) chunk = yield from self._content.read(chunk_size) - self._read_bytes += chunk_size + self._read_bytes += len(chunk) if self._read_bytes == self._length: self._at_eof = True assert b'\r\n' == (yield from self._content.readline()), \ diff --git a/tests/test_multipart.py b/tests/test_multipart.py index 2d0986d71b3..6860117c05a 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -74,6 +74,20 @@ def readline(self): return self.content.readline() +class StreamWithShortenRead(Stream): + + def __init__(self, content): + self._first = True + super().__init__(content) + + @asyncio.coroutine + def read(self, size=None): + if size is not None and self._first: + self._first = False + size = size // 2 + return super().read(size) + + class MultipartResponseWrapperTestCase(TestCase): def setUp(self): @@ -148,6 +162,22 @@ def test_read_chunk_requires_content_length(self): with self.assertRaises(AssertionError): yield from obj.read_chunk() + def test_read_chunk_properly_counts_read_bytes(self): + expected = b'.' * 10 + size = len(expected) + obj = aiohttp.multipart.BodyPartReader( + self.boundary, {'CONTENT-LENGTH': size}, + StreamWithShortenRead(expected + b'\r\n--:--')) + result = bytearray() + while True: + chunk = yield from obj.read_chunk() + if not chunk: + break + result.extend(chunk) + self.assertEqual(size, len(result)) + self.assertEqual(b'.' * size, result) + self.assertTrue(obj.at_eof()) + def test_read_does_reads_boundary(self): stream = Stream(b'Hello, world!\r\n--:') obj = aiohttp.multipart.BodyPartReader(