-
-
Notifications
You must be signed in to change notification settings - Fork 855
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add WebSocketException and support for WS handlers #527
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,12 @@ | |
import traceback | ||
import typing | ||
|
||
from starlette import status | ||
from starlette.concurrency import run_in_threadpool | ||
from starlette.requests import Request | ||
from starlette.requests import Request, empty_receive | ||
from starlette.responses import HTMLResponse, PlainTextResponse, Response | ||
from starlette.types import ASGIApp, Message, Receive, Scope, Send | ||
from starlette.websockets import WebSocket, WebSocketState | ||
|
||
STYLES = """ | ||
.traceback-container { | ||
|
@@ -83,7 +85,7 @@ def __init__( | |
self.debug = debug | ||
|
||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: | ||
if scope["type"] != "http": | ||
if scope["type"] not in {"http", "websocket"}: | ||
await self.app(scope, receive, send) | ||
return | ||
|
||
|
@@ -99,7 +101,7 @@ async def _send(message: Message) -> None: | |
try: | ||
await self.app(scope, receive, _send) | ||
except Exception as exc: | ||
if not response_started: | ||
if not response_started and scope["type"] == "http": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use |
||
request = Request(scope) | ||
if self.debug: | ||
# In debug mode, return traceback responses. | ||
|
@@ -115,6 +117,13 @@ async def _send(message: Message) -> None: | |
response = await run_in_threadpool(self.handler, request, exc) | ||
|
||
await response(scope, receive, send) | ||
elif scope["type"] == "websocket": | ||
websocket = WebSocket(scope, receive, send) | ||
# https://tools.ietf.org/html/rfc6455#section-7.4.1 | ||
# 1011 indicates that a server is terminating the connection because | ||
# it encountered an unexpected condition that prevented it from | ||
# fulfilling the request. | ||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is interesting... We shouldn't really have to do this, because the webserver's behavior ought to be in line with this anyway. We'd also want to check in this case that the websocket is in an open state. (The exception could have been raised after the websocket close.) I think that means we'd want a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's also not really clear if we want/need this in any case - In the HTTP case, we can use the handler to issue an application-custom 500 page. In the websocket case there's really nothing available for us to do other than close the the connection, which the server ought to take care of anyways. |
||
|
||
# We always continue to raise the exception. | ||
# This allows servers to log the error, or allows test clients | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reckon we should probably have
code
as a mandatory argument here, in line withHTTPException
.