Skip to content

Connection won't be closed if raise exception in AsyncHttpConsumer::handle() #1350

@kmiku7

Description

@kmiku7

Connection won't be closed when exception occurred in AsyncHttpConsumer::handle() and handle() have sent nothing using send() or send_body(). So client will be hanged there until timeout, with nothing received. In server-side, there is no exception traceback/information logged.
We can reproduce this case using following codes:

class DemoHttpConsumer(AsyncHttpConsumer):
  async def handle(self, body):
    raise ValueError()

I have read codes, it's because the exception occurred in handle() is ignore in

async def http_request(self, message):
"""
Async entrypoint - concatenates body fragments and hands off control
to ``self.handle`` when the body has been completely received.
"""
if "body" in message:
self.body.append(message["body"])
if not message.get("more_body"):
try:
await self.handle(b"".join(self.body))
finally:
await self.disconnect()
raise StopConsumer()

In finally statements, exception was ignored by raise StopConsumer(). So all coroutines will be waiting continues.

If send() something in AsyncHttpConsumer::handle(). Daphne will send {"type": "http.disconnect"} message in here:
https://github.com/django/daphne/blob/333f4644d1a5a167c85eca967a52e4e10a7db0bd/daphne/http_protocol.py#L257-L258

            if not message.get("more_body", False):
                self.finish()
                logger.debug("HTTP response complete for %s", self.client_addr)

which make all coroutines exit.

Now I am selecting a web-socket framework used in my company's project.
Because I am a novice in python asynchronies programming and channels, I'm sorry can't submit a patch to fix it. So can you fix this problem soon?

Activity

carltongibson

carltongibson commented on Sep 18, 2019

@carltongibson
Member

OK, thanks for the report. There are a bunch of issues around AsyncHttpConsumer, which is next on the list now. I'm hoping to have some time for it at the DjangoCon sprints next week.

self-assigned this
on Dec 2, 2019
IronJam11

IronJam11 commented on Jan 22, 2025

@IronJam11
Contributor

@carltongibson, if it is still open, i would like to work on this one

carltongibson

carltongibson commented on Jan 22, 2025

@carltongibson
Member

@IronJam11 You're welcome to look at it of course.

IronJam11

IronJam11 commented on Jan 28, 2025

@IronJam11
Contributor

I had a small question, when exactly is the http_disconnect function called in channels.generic.http.py

carltongibson

carltongibson commented on Jan 29, 2025

@carltongibson
Member

@IronJam11 It's called in the base class AsyncConsumer.dispatch. You might want to review the Consumers docs to make sure you're clear on the behaviour. Then read AsyncConsumer.__call__ to see how the ASGI spec is implemented. The consumer is the ASGI application (potentially wrapped by other applications, but you can ignore that).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @carltongibson@kmiku7@IronJam11

    Issue actions

      Connection won't be closed if raise exception in AsyncHttpConsumer::handle() · Issue #1350 · django/channels