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

Improve user feedback if no ws library installed #926

Merged
merged 6 commits into from
Feb 25, 2021

Conversation

euri10
Copy link
Member

@euri10 euri10 commented Dec 29, 2020

Fixes #797

@euri10 euri10 requested a review from a team December 29, 2020 15:35
docs/index.md Outdated Show resolved Hide resolved
try:
import websockets # noqa
except ImportError: # pragma: no cover
try:
import wsproto # noqa
except ImportError:
AutoWebSocketsProtocol = None
logger = logging.getLogger("uvicorn.error")
logger.warning(
Copy link
Member

@florimondmanca florimondmanca Dec 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this warning always trigger when using a minimal install?

I believe the default WS mode is "auto", meaning that we import this "auto protocol", which will be None and trigger this warning by default...

I'm actually not sure if/how we can check for "your app is using WebSocket, but dependencies aren't available" before a WebSocket request comes in.

So what we can do instead is log this warning when the first WebSocket connection request is received. Maybe that means we do need to define the "auto" protocol in this case as a "null protocol" class that logs this warning? I'm not sure how this None protocol is used by asyncio.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you nailed it, the ws flag is on auto by default, so AutoWebSocketsProtocol will be None, and we will get a warning set here if we try a handshake:

msg = "Unsupported upgrade request."

which sucks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what we can do instead is log this warning when the first WebSocket connection request is received. Maybe that means we do need to define the "auto" protocol in this case as a "null protocol" class that logs this warning? I'm not sure how this None protocol is used by asyncio.

like in the config.load() ? if ws_protocol_class is None > warning ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the current scenario is this:

  • uvicorn minimal > auto ws > ws=None > auto http > h11 > handshake in h11 > msg = "Unsupported upgrade request."

The present PR is preemptively raising a warning:

  • uvicorn minimal > auto ws > ws=None > Warning blablabla ws cant be used

We could also add this warning to the existing h11 warning:

  • uvicorn minimal > auto ws > ws=None > auto http > h11 > handshake in h11 > msg = "Unsupported upgrade request. Warning blablabla ws cant be used"

I just find it more deceptive when you want to use ws, but you'll have a useful info in both cases.

It's also true raising a warning for everyone when they dont want to use ws is probably annoying.

I have no preference, I let you choose ! :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok after trying to put the warning in the httptools_impl.py I find it weird.
the scenario is very deceptive for a user, and on top of that for a regular user using ws and having a real upgrade issue he'll have the warning, so I prefer to put it here in the import logic

@florimondmanca
Copy link
Member

@euri10 I think you put it right in the earlier comments:

Between "somewhat deceptive message only when receiving a WS request w/o a WS library" and "raise a message for all minimal users", I think the latter is less acceptable.

Should we update the "Unsupported upgrade request" warning instead? Perhaps do a quick runtime check on libraries and add an extra warning hint?

@euri10
Copy link
Member Author

euri10 commented Feb 25, 2021

@euri10 I think you put it right in the earlier comments:

Between "somewhat deceptive message only when receiving a WS request w/o a WS library" and "raise a message for all minimal users", I think the latter is less acceptable.

Should we update the "Unsupported upgrade request" warning instead? Perhaps do a quick runtime check on libraries and add an extra warning hint?

I had not thought about importing locally the AutoWebSocketsProtocol , it looks like a pretty alternative @florimondmanca

Copy link
Member

@florimondmanca florimondmanca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I like this.

uvicorn/protocols/http/h11_impl.py Outdated Show resolved Hide resolved
@@ -266,6 +266,11 @@ def handle_upgrade(self, event):
if upgrade_value != b"websocket" or self.ws_protocol_class is None:
msg = "Unsupported upgrade request."
self.logger.warning(msg)
from uvicorn.protocols.websockets.auto import AutoWebSocketsProtocol
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Nit) Let's add empty lines around this block so it's clearer that it's related but separate from the rest of the error handling code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like we're gtg :)

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

Successfully merging this pull request may close these issues.

Error during WebSocket handshake: Unexpected response code: 400 (anonymous) @ (index):16
2 participants