-
-
Notifications
You must be signed in to change notification settings - Fork 817
Description
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
channels/channels/generic/http.py
Lines 73 to 85 in f786fed
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 commentedon Sep 18, 2019
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.IronJam11 commentedon Jan 22, 2025
@carltongibson, if it is still open, i would like to work on this one
carltongibson commentedon Jan 22, 2025
@IronJam11 You're welcome to look at it of course.
IronJam11 commentedon Jan 28, 2025
I had a small question, when exactly is the http_disconnect function called in channels.generic.http.py
carltongibson commentedon Jan 29, 2025
@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 readAsyncConsumer.__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).