Skip to content
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

Path of Mount() being the initial substring of WebSocketRoute()'s blocks websocket with AssertionError: assert scope["type"] == "http" #1548

Closed
TrulyBright opened this issue Mar 19, 2022 · 2 comments

Comments

@TrulyBright
Copy link

TrulyBright commented Mar 19, 2022

Panicking code (uvicorn panicking:app):

# panicking.py
from starlette.applications import Starlette
from starlette.routing import WebSocketRoute, Mount
from starlette.websockets import WebSocket, WebSocketDisconnect
from starlette.staticfiles import StaticFiles

async def endpoint(ws: WebSocket):
    await ws.accept()
    try:
        while msg := await ws.receive():
            ws._raise_on_disconnect(msg)
            print(msg)
    except WebSocketDisconnect:
        pass
    finally:
        await ws.close()

app = Starlette(debug=True, routes=[
    Mount("/", StaticFiles(directory="dist")),
    WebSocketRoute("/foo", endpoint),
])

The raised error log when I tried connecting to ws://localhost:8000/foo:

  File "C:@@@\.venv\lib\site-packages\uvicorn\protocols\websockets\websockets_impl.py", line 184, in run_asgi
    result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
  File "C:@@@\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
    return await self.app(scope, receive, send)
  File "C:@@@\.venv\lib\site-packages\starlette\applications.py", line 119, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:@@@\.venv\lib\site-packages\starlette\middleware\errors.py", line 146, in __call__
    await self.app(scope, receive, send)
  File "C:@@@\.venv\lib\site-packages\starlette\exceptions.py", line 66, in __call__
    await self.app(scope, receive, send)
  File "C:@@@\.venv\lib\site-packages\starlette\routing.py", line 666, in __call__
    await route.handle(scope, receive, send)
  File "C:@@@\.venv\lib\site-packages\starlette\routing.py", line 418, in handle
    await self.app(scope, receive, send)
    assert scope["type"] == "http"
AssertionError

Working code where the path of WebSocketRoute no longer starts with that of Mount (uvicorn working:app):

# panicking.py
from starlette.applications import Starlette
from starlette.routing import WebSocketRoute, Mount
from starlette.websockets import WebSocket, WebSocketDisconnect
from starlette.staticfiles import StaticFiles

async def endpoint(ws: WebSocket):
    await ws.accept()
    try:
        while msg := await ws.receive():
            ws._raise_on_disconnect(msg)
            print(msg)
    except WebSocketDisconnect:
        pass
    finally:
        await ws.close()

app = Starlette(debug=True, routes=[
    Mount("/bar", StaticFiles(directory="dist")),
    WebSocketRoute("/foo", endpoint),
])

So the raised error is not clear enough to figure out the actual problem.
Version:

  • uvicorn: 0.17.6 with CPython 3.10.2 on Windows
  • starlette: 0.19.0
@TrulyBright TrulyBright changed the title Path() and Mount() sharing same path blocks websocket with AssertionError: assert scope["type"] == "http" Route() and Mount() sharing same path blocks websocket with AssertionError: assert scope["type"] == "http" Mar 19, 2022
@TrulyBright TrulyBright changed the title Route() and Mount() sharing same path blocks websocket with AssertionError: assert scope["type"] == "http" Route() and Mount() sharing same path block websocket with AssertionError: assert scope["type"] == "http" Mar 19, 2022
@TrulyBright TrulyBright changed the title Route() and Mount() sharing same path block websocket with AssertionError: assert scope["type"] == "http" Path of Mount() being the initial substring of WebSocketRoute()'s blocks websocket with AssertionError: assert scope["type"] == "http" Mar 19, 2022
@TrulyBright
Copy link
Author

TrulyBright commented Mar 19, 2022

It solves the error to insert all WebSocketRoute()s before Mount() into routes, without modifying their paths, though the actual problem is the unclearness of the raised error.

app = Starlette(debug=True, routes=[
    WebSocketRoute("/foo", endpoint),
    Mount("/", StaticFiles(directory="dist")),
]) # works fine

@Kludex
Copy link
Sponsor Member

Kludex commented Mar 19, 2022

Your client is trying to access the wrong route.

Check https://www.starlette.io/routing/#route-priority for more details.

Suggestions to improve the error message are welcome, but in this case, I can't think of a useful message considering the cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants