Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
1 task done
ddurham2 opened this issue Mar 27, 2023 · 3 comments
Closed
1 task done

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

ddurham2 opened this issue Mar 27, 2023 · 3 comments
Labels

Comments

@ddurham2
Copy link

ddurham2 commented Mar 27, 2023

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: andrew.svetlov@gmail.com
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: andrew.svetlov@gmail.com
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
@ddurham2 ddurham2 added the bug label Mar 27, 2023
@Dreamsorcerer
Copy link
Member

If you could pop that fix into a PR with a test, that'd be great.

@yoelbassin
Copy link

From what I see this issue was fixed in #5380 with a great test that matches the issue you described.

    filepath = pathlib.Path(__file__).parent / "data.zero_bytes"

    async def handler(request):
        asyncio.set_event_loop(loop_with_mocked_native_sendfile)
        return web.FileResponse(filepath)

Could you provide more detailed instructions to reproduce your issue?

@ddurham2
Copy link
Author

It does look like that'll fix it, I was not on the latest release. It's working now. Thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants