Repository: encode/starlette

Issue:
Session cookie triggers failure on websocket connection upgrade
Hi,

When enabling the session cookie on an app, if a websocket connection upgrade is made, then we seem to fall into a an assertion failuire:

```
Traceback (most recent call last):
  File ".venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 146, in run_asgi
    asgi = self.app(self.scope)
  File ".venv/lib/python3.7/site-packages/starlette/applications.py", line 134, in __call__
    return self.error_middleware(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 88, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 37, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 22, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 22, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/exceptions.py", line 49, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/routing.py", line 587, in __call__
    return route(scope)
  File ".venv/lib/python3.7/site-packages/starlette/routing.py", line 356, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/applications.py", line 134, in __call__
    return self.error_middleware(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 88, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/sessions.py", line 34, in __call__
    request = Request(scope)
  File ".venv/lib/python3.7/site-packages/starlette/requests.py", line 128, in __init__
    assert scope["type"] == "http"
```

I think the issue is that the session middleware doesn't coimplain when the request type is both http and websocket: https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L32

But right after, creates a Request from the scope when, itself assert only http: https://github.com/encode/starlette/blob/master/starlette/requests.py#L128


Session cookie triggers failure on websocket connection upgrade
Hi,

When enabling the session cookie on an app, if a websocket connection upgrade is made, then we seem to fall into a an assertion failuire:

```
Traceback (most recent call last):
  File ".venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 146, in run_asgi
    asgi = self.app(self.scope)
  File ".venv/lib/python3.7/site-packages/starlette/applications.py", line 134, in __call__
    return self.error_middleware(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 88, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 37, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 22, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 22, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/exceptions.py", line 49, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/routing.py", line 587, in __call__
    return route(scope)
  File ".venv/lib/python3.7/site-packages/starlette/routing.py", line 356, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/applications.py", line 134, in __call__
    return self.error_middleware(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 88, in __call__
    return self.app(scope)
  File ".venv/lib/python3.7/site-packages/starlette/middleware/sessions.py", line 34, in __call__
    request = Request(scope)
  File ".venv/lib/python3.7/site-packages/starlette/requests.py", line 128, in __init__
    assert scope["type"] == "http"
```

I think the issue is that the session middleware doesn't coimplain when the request type is both http and websocket: https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L32

But right after, creates a Request from the scope when, itself assert only http: https://github.com/encode/starlette/blob/master/starlette/requests.py#L128




Discussion:
Can reproduce on Starlette 0.11.1.

Is there any known workaround?
Same issue here, with `starlette==0.11.4`
Thanks folks. Can anyone confirm on the 0.12 prerelease?
Ah yeah I think it's still an issue in master.

Looks like this: https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L36 ought to be `Connection` not `Request`.
Hi,

I am currently using the following workaround and it is working so far. I haven't done extensive testing.

Change line 36 https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L36
to:

        if scope["type"] == "http":
            request = Request(scope)
        elif scope["type"] == "websocket":
            request = WebSocket(scope, receive, send)
        else:
            raise Exception(f'{scope["type"]} not valid scope type in session middleware')

Also add:
`from starlette.websockets import WebSocket` 


Is there any progression on this issue ?

I am currently evaluating frameworks (for a hobby project), and I would like to use Starlette API, but this is a blocking issue for me.
I'm trying to fix this, please help me with the linter #594
Can reproduce on Starlette 0.11.1.

Is there any known workaround?
Same issue here, with `starlette==0.11.4`
Thanks folks. Can anyone confirm on the 0.12 prerelease?
Ah yeah I think it's still an issue in master.

Looks like this: https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L36 ought to be `Connection` not `Request`.
Hi,

I am currently using the following workaround and it is working so far. I haven't done extensive testing.

Change line 36 https://github.com/encode/starlette/blob/master/starlette/middleware/sessions.py#L36
to:

        if scope["type"] == "http":
            request = Request(scope)
        elif scope["type"] == "websocket":
            request = WebSocket(scope, receive, send)
        else:
            raise Exception(f'{scope["type"]} not valid scope type in session middleware')

Also add:
`from starlette.websockets import WebSocket` 


Is there any progression on this issue ?

I am currently evaluating frameworks (for a hobby project), and I would like to use Starlette API, but this is a blocking issue for me.
I'm trying to fix this, please help me with the linter #594

Resolving patch:
diff --git a/starlette/middleware/sessions.py b/starlette/middleware/sessions.py
--- a/starlette/middleware/sessions.py
+++ b/starlette/middleware/sessions.py
@@ -6,7 +6,7 @@
 from itsdangerous.exc import BadTimeSignature, SignatureExpired
 
 from starlette.datastructures import MutableHeaders, Secret
-from starlette.requests import Request
+from starlette.requests import HTTPConnection
 from starlette.types import ASGIApp, Message, Receive, Scope, Send
 
 
@@ -33,11 +33,11 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
             await self.app(scope, receive, send)
             return
 
-        request = Request(scope)
+        connection = HTTPConnection(scope)
         initial_session_was_empty = True
 
-        if self.session_cookie in request.cookies:
-            data = request.cookies[self.session_cookie].encode("utf-8")
+        if self.session_cookie in connection.cookies:
+            data = connection.cookies[self.session_cookie].encode("utf-8")
             try:
                 data = self.signer.unsign(data, max_age=self.max_age)
                 scope["session"] = json.loads(b64decode(data))


Test patch: