falcon: Websocket handler fails in some cases of HTTPError/HTTPStatus
Hi,
Writing ASGI falcon using websockets, using the process_request_ws middleware handler and app.add_error_handler(HTTPError, my_error_handler) error handler.
When raising a falcon.HTTPError in the middleware its picked up by the error handler via the ex param.
The object is not none, however this is my stacktrace:
I raise the “falcon.http_error.HTTPError: <HTTPError: 403 Forbidden>” in the middleware, and then raise the “falcon.http_error.HTTPError: <HTTPError: 500>” in the error handler, which results in the final traceback (falcon internal).
'''
[2023-03-29 13:39:47 +0200] [82450] [INFO] ('127.0.0.1', 57224) - "WebSocket /message" 403
[2023-03-29 13:39:47 +0200] [82450] [ERROR] Exception in ASGI application
Traceback (most recent call last):
File ".pyenv/versions/wm/lib/python3.11/site-packages/falcon/asgi/app.py", line 1000, in _handle_websocket
await process_request_ws(req, web_socket)
File "Desktop/mirror/whatsapp-service/whatsapp_service/middleware/basic_ws_middleware.py", line 106, in process_request_ws
raise HTTPError(status=falcon.HTTP_403, title="Invalid header")
falcon.http_error.HTTPError: <HTTPError: 403 Forbidden>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".pyenv/versions/wm/lib/python3.11/site-packages/falcon/asgi/app.py", line 1095, in _handle_exception
await err_handler(req, resp, ex, params, **kwargs)
File "Desktop/mirror/whatsapp-service/whatsapp_service/utils/handlers/error_handlers.py", line 24, in my_error_handler
raise HTTPError(status=500, title='Custom Websocket Error')
falcon.http_error.HTTPError: <HTTPError: 500>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".pyenv/versions/wm/lib/python3.11/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 238, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".pyenv/versions/wm/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".pyenv/versions/wm/lib/python3.11/site-packages/falcon/asgi/app.py", line 312, in __call__
await self._handle_websocket(spec_version, scope, receive, send)
File ".pyenv/versions/wm/lib/python3.11/site-packages/falcon/asgi/app.py", line 1018, in _handle_websocket
if not await self._handle_exception(req, None, ex, params, ws=web_socket):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".pyenv/versions/wm/lib/python3.11/site-packages/falcon/asgi/app.py", line 1100, in _handle_exception
self._compose_error_response(req, resp, error)
File "falcon/app.py", line 975, in falcon.app.App._compose_error_response
'''
The usage of the method resolution order is incorrect here as the type(exc) invocation returns type not the exception:
https://github.com/falconry/falcon/blob/18503813059e648c693d03064adf2acdbe68d654/falcon/app.py#L1001
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 18 (10 by maintainers)
btw thanks @sashn-citiqprepaid for supplying a complete example that reproduced your issue
I don’t think so.
The issue is that error raised in error handlers when using websockets were not correctly considered by falcon, so we try to serialize it on the a response object that missing since it’s a websocket response.
A workaround is to instead of raising the error in the error handler, to close the websocket if the websocket object is provided to the handler
Hi @vytas7 .
It might be my implementation that is unexpected, but worth exploring. Will put together an example.