Skip to content

Using web.FileResponse to send an empty file causes an error #7242

Closed
@ddurham2

Description

@ddurham2

Describe the bug

If a web.FileResponse() is used to send an empty file, then the following stack trace is raise...

  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 485, in start
    resp, reset = await task
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 440, in _handle_request
    reset = await self.finish_response(request, resp, start_time)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 591, in finish_response
    await prepare_meth(request)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_fileresponse.py\", line 241, in prepare
    return await self._sendfile(request, fobj, offset, count)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_fileresponse.py\", line 96, in _sendfile
    await loop.sendfile(transport, fobj, offset, count)
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 1120, in sendfile
    return await self._sendfile_native(transport, file,
  File \"/usr/lib/python3.8/asyncio/selector_events.py\", line 578, in _sendfile_native
    return await self.sock_sendfile(transp._sock, file, offset, count,
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 836, in sock_sendfile
    self._check_sendfile_params(sock, file, offset, count)
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 889, in _check_sendfile_params
    raise ValueError(

So, it's actually an error to call asyncio's sendfile() function with 0 bytes.. which seems like something they would have short-circuited on purpose, but apparently have not.

Nevertheless, it was easily fixed in web.file_response.py ~96 just to add an if count > 0 around calling sendfile. And that resulted in the expected 200 response with content-length of 0.

To Reproduce

return web.FileResponse(path="/dev/null")
or
return web.FileResponse(path="/path/to/requested-resource/that-happens/to-have-zero-size")

Expected behavior

correct 200 response just with 0 length.

Logs/tracebacks

File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 485, in start
    resp, reset = await task
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 440, in _handle_request
    reset = await self.finish_response(request, resp, start_time)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_protocol.py\", line 591, in finish_response
    await prepare_meth(request)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_fileresponse.py\", line 241, in prepare
    return await self._sendfile(request, fobj, offset, count)
  File \"/usr/local/lib/python3.8/dist-packages/aiohttp/web_fileresponse.py\", line 96, in _sendfile
    await loop.sendfile(transport, fobj, offset, count)
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 1120, in sendfile
    return await self._sendfile_native(transport, file,
  File \"/usr/lib/python3.8/asyncio/selector_events.py\", line 578, in _sendfile_native
    return await self.sock_sendfile(transp._sock, file, offset, count,
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 836, in sock_sendfile
    self._check_sendfile_params(sock, file, offset, count)
  File \"/usr/lib/python3.8/asyncio/base_events.py\", line 889, in _check_sendfile_params
    raise ValueError(

Python Version

$ python --version
Python 3.8.10

aiohttp Version

$ python -m pip show aiohttp
Name: aiohttp
Version: 3.8.4
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: None
Author-email: None
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: charset-normalizer, frozenlist, attrs, async-timeout, multidict, aiosignal, yarl
Required-by: pyht, keycloak-api, htdm, aiohttp-jinja2

multidict Version

$ python -m pip show multidict
Name: multidict
Version: 6.0.4
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: 
Required-by: yarl, aiohttp

yarl Version

$ python -m pip show yarl
Name: yarl
Version: 1.8.2
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: multidict, idna
Required-by: aiohttp

OS

uname -a
Linux myhost 5.10.0-0.deb10.17-amd64 #1 SMP Debian 5.10.136-1~deb10u3 (2022-09-06) x86_64 x86_64 x86_64 GNU/Linux

Related component

Server

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions