pgjones / hypercorn

Hypercorn is an ASGI and WSGI Server based on Hyper libraries and inspired by Gunicorn.
MIT License
1.17k stars 104 forks source link

Statsd logger raises exception in v0.16.0 #211

Closed BrandonWiebe closed 5 months ago

BrandonWiebe commented 7 months ago

Upon upgrading to Hypercorn v0.16.0 from 0.14.4, enabling the statsd logger results in an exception being raised from hypercorn after each request. This issue is present in v0.15.0 as well.

This can be reproduced absent of any other framework using the "Hello World" example given in the Quickstart section of the documentation:

# hello_world.py
import asyncio

from hypercorn.asyncio import serve
from hypercorn.config import Config

async def app(scope, receive, send):
    if scope["type"] != "http":
        raise Exception("Only the HTTP protocol is supported")

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            (b'content-type', b'text/plain'),
            (b'content-length', b'5'),
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'hello',
    })

if __name__ == "__main__":
    config = Config()
    config.statsd_host = "0.0.0.0:8125"

    asyncio.run(serve(app, config))

Running the above code, each request given to the server results in the following traceback:

Traceback (most recent call last):
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.py", line 27, in _handle
    await app(scope, receive, send, sync_spawn, call_soon)
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/app_wrappers.py", line 34, in __call__
    await self.app(scope, receive, send)
  File "/home/brandon/./hello_world.py", line 19, in app
    await send({
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py", line 190, in app_send
    await self.send(StreamClosed(stream_id=self.stream_id))
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/protocol/h11.py", line 145, in stream_send
    await self._maybe_recycle()
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/protocol/h11.py", line 265, in _maybe_recycle
    await self._close_stream()
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/protocol/h11.py", line 287, in _close_stream
    await self.stream.handle(StreamClosed(stream_id=STREAM_ID))
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py", line 113, in handle
    await self.config.log.access(self.scope, None, time() - self.start_time)
  File "/home/brandon/.venv/lib/python3.9/site-packages/hypercorn/statsd.py", line 75, in access
    await self.increment(f"hypercorn.request.status.{response['status']}", 1)
TypeError: 'NoneType' object is not subscriptable
pgjones commented 5 months ago

Fixed in aee69f5fcc5dda48e33e6566e9068d4fe03c1e30