From 23ce1985a1eb4eb185fc97bbf6b754bd04dbe8e6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 25 Oct 2020 01:41:22 -0500 Subject: [PATCH] Ensure zero byte files can be sent (#5125) --- CHANGES/5124.bugfix | 1 + aiohttp/web_fileresponse.py | 8 +++++++- tests/data.zero_bytes | 0 tests/test_web_sendfile_functional.py | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 CHANGES/5124.bugfix create mode 100644 tests/data.zero_bytes diff --git a/CHANGES/5124.bugfix b/CHANGES/5124.bugfix new file mode 100644 index 00000000000..7726a6bbe3a --- /dev/null +++ b/CHANGES/5124.bugfix @@ -0,0 +1 @@ +Ensure sending a zero byte file does not throw an exception diff --git a/aiohttp/web_fileresponse.py b/aiohttp/web_fileresponse.py index bb84c4eca33..6b98c565788 100644 --- a/aiohttp/web_fileresponse.py +++ b/aiohttp/web_fileresponse.py @@ -98,7 +98,13 @@ async def sendfile(self) -> None: if hasattr(loop, "sendfile"): # Python 3.7+ self.transport.write(data) - await loop.sendfile(self.transport, self._fobj, self._offset, self._count) + if self._count != 0: + await loop.sendfile( + self.transport, + self._fobj, + self._offset, + self._count + ) await super().write_eof() return diff --git a/tests/data.zero_bytes b/tests/data.zero_bytes new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/test_web_sendfile_functional.py b/tests/test_web_sendfile_functional.py index 91f2dbbec2a..3f373382d5d 100644 --- a/tests/test_web_sendfile_functional.py +++ b/tests/test_web_sendfile_functional.py @@ -45,6 +45,25 @@ async def handler(request): await resp.release() +async def test_zero_bytes_file_ok(aiohttp_client, sender) -> None: + filepath = pathlib.Path(__file__).parent / "data.zero_bytes" + + async def handler(request): + return sender(filepath) + + app = web.Application() + app.router.add_get("/", handler) + client = await aiohttp_client(app) + + resp = await client.get("/") + assert resp.status == 200 + txt = await resp.text() + assert "" == txt.rstrip() + assert "application/octet-stream" == resp.headers["Content-Type"] + assert resp.headers.get("Content-Encoding") is None + await resp.release() + + async def test_static_file_ok_string_path(aiohttp_client, sender) -> None: filepath = pathlib.Path(__file__).parent / "data.unknown_mime_type"