HTTPStream.app_send is missing http.disconnect handling ?
See original GitHub issuetl;dr
I don’t see the code responsible for handling http.disconnect
in http stream:
https://github.com/pgjones/hypercorn/blob/8cef567301a5a3f4363d1c2cad76008e58add8aa/src/hypercorn/protocol/http_stream.py#L117-L177
It looks like an omission to me, especially given the websocket stream has code for handling it corresponding websocket.close
Long versions
I’ve written a simple middleware to simulate the asgi app being not responsive:
class AsgiOfflineMiddleware:
def __init__(self, asgi_app):
self.asgi_app = asgi_app
self._offline_ports = set()
self._offline_watchdogs_parking = trio.lowlevel.ParkingLot()
@contextmanager
def offline(self, port: int):
assert port not in self._offline_ports
self._offline_ports.add(port)
self._offline_watchdogs_parking.unpark_all()
try:
yield
finally:
self._offline_ports.remove(port)
# No need to unpark given our port has just been re-authorized !
async def __call__(self, scope, receive, send):
# Special case for lifespan given it corresponds to server init and not
# to an incoming client connection
if scope["type"] == "lifespan":
return await self.asgi_app(scope, receive, send)
port = scope["server"][1]
pretend_to_be_offline = False
if port in self._offline_ports:
pretend_to_be_offline = True
else:
async def _offline_watchdog(cancel_scope):
nonlocal pretend_to_be_offline
while True:
await self._offline_watchdogs_parking.park()
if port in self._offline_ports:
break
pretend_to_be_offline = True
cancel_scope.cancel()
async with trio.open_nursery() as nursery:
nursery.start_soon(_offline_watchdog, nursery.cancel_scope)
await self.asgi_app(scope, receive, send)
nursery.cancel_scope.cancel()
if pretend_to_be_offline:
if scope["type"] == "http":
await send({"type": "http.disconnect"})
elif scope["type"] == "websocket":
await send({"type": "websocket.close"})
else:
assert False, scope
However it produce errors when trying to close an HTTP connection:
ERROR hypercorn.error:logging.py:100 Error in ASGI Framework
Traceback (most recent call last):
File "C:\Users\gbleu\source\repos\parsec-cloud\venv39\lib\site-packages\hypercorn\trio\task_group.py", line 21, in _handle
await invoke_asgi(app, scope, receive, send)
File "C:\Users\gbleu\source\repos\parsec-cloud\venv39\lib\site-packages\hypercorn\utils.py", line 247, in invoke_asgi
await app(scope, receive, send)
File "C:\Users\gbleu\source\repos\parsec-cloud\parsec-cloud\tests\common\backend.py", line 427, in __call__
await send({"type": "http.disconnect"})
File "C:\Users\gbleu\source\repos\parsec-cloud\venv39\lib\site-packages\hypercorn\protocol\http_stream.py", line 177, in app_send
raise UnexpectedMessageError(self.state, message["type"])
hypercorn.utils.UnexpectedMessageError: Unexpected message type, http.disconnect given the state ASGIHTTPState.REQUEST
Issue Analytics
- State:
- Created a year ago
- Comments:5 (5 by maintainers)
Top Results From Across the Web
AsyncHttpConsumer regression and disconnect handling #1249
Our library implements handle , which returns quickly and spawns a subtask to handle the ongoing stream. At the time the code was...
Read more >ASGI http.disconnect not handled on requests with body.
http.disconnect is designed for long-polling — so we imagine a client opening a request, with a request body, and then disconnecting before the...
Read more >C++ Tutorial: Sockets - Server & Client - 2020 - BogoToBogo
A client app send a request to a server app. The server app returns a ... The most common types are stream sockets...
Read more >End User Authorization Flows - Zoom App Marketplace
If a user is unable to install an app from the Marketplace, the user can view which missing permissions need to be granted...
Read more >Execute some action when client disconnects from hot stream
The exception is related to HTTP connection handling between the browser ant the controller (simply put). It can be handled in controller's ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Hi. According to the spec,
http.disconnect
is an asgi receive event instead of send event, so you can not close the http connection in that way. Return 500 error would be ok.thanks a lot @synodriver 😃 🎉
so it’s
websocket.close
that is the event the application send, andwebsocket.disconnect
(andhttp.disconnect
) that are send to the application !