Channels 2 not persisting session data set in `connect`
See original GitHub issue- Your OS and runtime environment, and browser if applicable Development. Running a Django application from Pycharm.
- The versions of Channels, Daphne, Django, Twisted, and your ASGI backend (channels_redis normally)
channels==2.1.2 channels-redis==2.2.1 daphne==2.2.0 Django==1.11.6
- What you expected to happen vs. what actually happened
I’ve upgraded to Channels 2 specifically for the ability to access and modify the session from within a consumer, but that doesn’t seem to be the case. Basically, I want to identify AnonymousUser
s and send them messages (each one, not all of them together)
Here’s my routing.py
file:
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
core.routing.websocket_urlpatterns
)
),
})
Here’s my consumers.py
file:
class ChatConsumer(WebsocketConsumer):
def connect(self):
if self.scope['user'].is_authenticated:
user_id = str(self.scope['user'].id)
self.scope['session']['user_identifier']= user_id
self.group_name = user_id
else:
user_id = str(self.scope['user']) + str(uuid.uuid4())
self.scope['session']['user_identifier'] = user_id
self.group_name = user_id
self.scope['session'].save()
print(f" in consumer: {self.scope['session']['user_identifier']}")
# Join room group
async_to_sync(self.channel_layer.group_add)(
self.group_name,
self.channel_name
)
self.accept()
And in the view where I need to send, I’m trying to get the group_name (user_identifier
) from the session in case of an AnonymousUser:
def get_spotify_link(request):
if request.user.is_authenticated:
user_identifier = str(request.user.id)
else:
user_identifier = request.session['user_identifier']
print(f"in get_spotify_link: {user_identifier}")
However, I’m intermittently (95% of the time) getting KeyError: 'user_identifier'
.
- How you’re running Channels (runserver? daphne/runworker? Nginx/Apache in front?) runserver
- Console logs and full tracebacks of any errors
Internal Server Error: /get_spotify_link/
Traceback (most recent call last):
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/myusername/PycharmProjects/artist_notify/core/views.py", line 442, in get_spotify_link
user_identifier = request.session['user_identifier']
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 57, in __getitem__
return self._session[key]
KeyError: 'user_identifier'
[2018/07/08 20:54:03] WebSocket HANDSHAKING / [127.0.0.1:65478]
in consumer: AnonymousUser8883761c-f673-413e-82e2-413d1cbb17e3
[2018/07/08 20:54:03] WebSocket CONNECT / [127.0.0.1:65478]
Internal Server Error: /get_spotify_link/
Traceback (most recent call last):
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/myusername/PycharmProjects/artist_notify/core/views.py", line 442, in get_spotify_link
user_identifier = request.session['user_identifier']
File "/Users/myusername/.virtualenvs/bap_dev/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 57, in __getitem__
return self._session[key]
KeyError: 'user_identifier'
Issue Analytics
- State:
- Created 5 years ago
- Comments:13 (5 by maintainers)
I am also experiencing this. My django right now only has a websocket endpoint (no views) and the session_key changes during every connect:
This issue should be reopened @andrewgodwin
Hi @andrewgodwin I’m also seeing the same problem. I’m not using celery at all.
I’ve tried the default session storage as well as this 3rd party driver: https://github.com/martinrusev/django-redis-sessions
It appears that the session cookie is not being set in the browser when
scope["session"].save()
is called.Then refreshing my page which makes the websocket connection twice results in the following logs:
The javascript code to connect is straight from the tutorial. The following middleware is applied:
No cookies are set in the browser.
Is there something missing here? Happy to open new ticket if this appears to be a different issue.
Thanks.
Edit:
It appears that if I use the session elsewhere first, it works. For instance, I call
request.session.set_test_cookie()
in another (completely unrelated) django view. Then, as long as the sessionId cookie has been set first, it works fine. But the sessionId key must be set first. This makes sense since the session state is updated in the session store and the cookie can pass the unchanged sessionId to reference the session state.I thought cookies could be set during the ws handshake but maybe this is not the case or has recently changed. If I’m missing something please let me know.
Solution:
Modify the session once before connection with websockets so that the sessionId is set in the browser. Then session persistence should work. This won’t work with the cookie session backend.