Closed twillis closed 4 years ago
In addition to the issue of the asgiref
upgrade, there is also an infinite loop upon disconnect:
async def asgi_instance(receive, send):
while True:
message = await receive()
if message["type"] == "websocket.connect":
...
if message["type"] == "websocket.receive":
...
should be changed to:
async def asgi_instance(receive, send):
while True:
message = await receive()
if message["type"] == "websocket.connect":
...
elif message["type"] == "websocket.receive":
...
elif message["type"] == "websocket.disconnect":
break
Apologies for missing @twillis's PR. @IftachSadeh thank you for the review! I made the change, and pushed it to twillis's branch. Please let me know if the updated PR looks good to y'all and I will merge it.
Thanks @stevepiercy . The example runs well now. One small caveat - on leaving the page, one gets an exception:
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 153, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
File "venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
......
File "venv/lib/python3.7/site-packages/asgiref/wsgi.py", line 35, in __call__
raise ValueError("WSGI wrapper received a non-HTTP scope")
ValueError: WSGI wrapper received a non-HTTP scope
Is this the expected behaviour? If so, you can change to:
async def __call__(self, scope, *args, **kwargs):
protocol = scope["type"]
path = scope["path"]
try:
consumer = self.protocol_router[protocol][path]
except KeyError:
consumer = None
if consumer is not None:
await consumer(scope, *args, **kwargs)
try:
await super().__call__(scope, *args, **kwargs)
except ValueError as e:
pass
except Exception as e:
raise e
I don't know whether that behavior is expected or not, but putting a pass
for an exception does not feel right. I'd look to the source code for the error message, then determine what would be more useful to return to the user as an error message than the default, specifically scope["type"]
. Perhaps that gives you some more information on how to improve this bit?
On leaving the page the scope['type']
is websocket
. Do you know why this is?
I'm not sure if there's any sense in taking some action. Maybe the following fix would be ok:
try:
if scope['type'] == 'http':
await super().__call__(scope, *args, **kwargs)
except Exception as e:
raise e
I am still new to ASGI, so I don't have much to offer as an explanation. I can read docs about ASGI and websocket but that doesn't mean I understand them. I think many of us are still trying to figure out best practices with ASGI. "Perfection is the enemy of progress", and this PR makes good progress. Therefore I'll push a comment into the PR, referring to this discussion, and merge it as is. That will give the recipe better public exposure and potential for continued improvement.
As a cookbook recipe, the chef may follow the essential instructions and add code to taste. If someone in the future comes up with a definitive improvement, then we can update the recipe.
Closed by #226
I'm guessing there has been some change to asgi since this was written, however I lack the experience to figure it out on my own and submit a pr.
considering the time this was merged my guess would be that the example is not compatible with asgi 3.0. hoping the author @erm might be able to offer some guidance on this.
https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/deployment/asgi.html original submission: https://github.com/Pylons/pyramid_cookbook/pull/198
pinning asgiref==2.3.2 fixes things.