aiohttp icon indicating copy to clipboard operation
aiohttp copied to clipboard

Enabling gzip compression throws exception on 204 No content responses

Open dchaplinsky opened this issue 7 years ago • 2 comments

Long story short

I've enabled gzip compression like that but it throws exception on 204 responses

Expected behaviour

Do not throw exception if body is absent

Actual behaviour

Traceback (most recent call last):
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_protocol.py", line 398, in start
    await resp.prepare(request)
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_response.py", line 300, in prepare
    return await self._start(request)
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_response.py", line 605, in _start
    return await super()._start(request)
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_response.py", line 329, in _start
    self._start_compression(request)
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_response.py", line 290, in _start_compression
    self._do_start_compression(coding)
  File "my_awesome_project/venv/lib/python3.6/site-packages/aiohttp/web_response.py", line 616, in _do_start_compression
    self._compressed_body = compressobj.compress(self._body) +\
TypeError: a bytes-like object is required, not 'NoneType'

Steps to reproduce


async def enable_compression(request, response):
    response.enable_compression()
....

app.on_response_prepare.append(remove_server_header)
....

but when I do

async def whatever(request):
    raise web.HTTPNoContent()

exception above happens

Your environment

python 3.6.5 aiohttp (both) 3.3.2 MacOS 10.13.5 (17F77)

dchaplinsky avatar Jul 30 '18 14:07 dchaplinsky


from aiohttp import web

async def enable_compression(request, response):
    # Only enable compression if response has a body
    if response.body is not None:
        response.enable_compression()

async def remove_server_header(request, response):
    response.headers.pop('Server', None)

async def whatever(request):
    raise web.HTTPNoContent()

app = web.Application()
app.on_response_prepare.append(enable_compression)
app.on_response_prepare.append(remove_server_header)

app.router.add_get('/', whatever)

if __name__ == '__main__':
    web.run_app(app)

ljluestc avatar Feb 10 '24 20:02 ljluestc

I suspect this assert should be changed to be part of the if statement: https://github.com/aio-libs/aiohttp/blob/0ec65c0f4dc08d027f659256b09ae9cff10ab404/aiohttp/web_response.py#L707

If someone can add a test that reproduces the issue with a 204 response, then we can fix that.

Dreamsorcerer avatar Feb 10 '24 21:02 Dreamsorcerer