aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
14.98k stars 2k forks source link

Redirect on ws_connect gives confusing result #3678

Open xim opened 5 years ago

xim commented 5 years ago

Long story short

I'm implementing a websocket service on existing HTTP server software. The server can be (and is by default) configured to redirect all HTTP traffic to HTTPS. The clients can choose to connect over HTTP or HTTPS. When connecting to ws://service/ws you will get a redirect to https://service/ws if the server is running with HTTP redirect to HTTPS.

Allowing ws_connect(..., allow_redirects=False) would at least allow me to detect this scenario without assuming that an HTTP 401 means "you got an HTTP Redirect, and followed it after dropping credentials."

Expected behaviour

ws_connect('ws://service/ws', auth=auth) -> either a redirect related error or success

Actual behaviour

The client gets HTTP 401, as credentials aren't included in the redirected request.

Steps to reproduce

ws_connect('ws://service/ws', auth=auth) against a server that redirects HTTP traffic to HTTPS and requires basic auth.

Your environment

Python 3.7.3rc1, aiohttp 3.5.1 (client)

Server is nginx with a boost::beast websocket service running behind a reverse proxy on /ws.

xim commented 5 years ago

I wouldn't mind making a pull request for this if I knew which were the more desirable solution; Adding allow_redirects as a possible keyword argument to ws_connect? Throwing an error in all cases where a redirect would cause credentials to be dropped?

xim commented 5 years ago

Apparently, the test that finds out auth should be dropped is if url.origin() != r_url.origin() -- so a redirect from ws://foo/ to https://foo/ appears to be what triggers this. Shouldn't auth be preserved through a redirect from HTTP to HTTPS?

New list of options:

  1. Add allow_redirects as a possible keyword argument to ws_connect and pass to request()
  2. Throw an error in all cases where a redirect would cause credentials to be dropped..
  3. Keep auth if redirecting, according to one of these:
    • Going from {ws,http}://origin to https://origin.
    • Any redirect going to HTTPS.
    • If new argument keep_auth_on_redirect is true.