Everything is working fine on Firefox/IE, but on Chrome I keep getting the "Sent non-empty 'Sec-WebSocket-Protocol' header but no response was receive" error. Any ideas on why this is happening and how to fix it?
js
var roomid = 'roomname'
var endpoint = 'ws://'+ window.location.host + window.location.pathname
var socket = new WebSocket(endpoint, roomid)
consumers.py
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
chat_room = str(self.scope['subprotocols']).replace('[','').replace(']','').replace("'",'')
self.chat_room = chat_room
await self.channel_layer.group_add(
chat_room,
self.channel_name)
await self.send({"type": "websocket.accept"}
(Using windows 10, localhost)
There's this StackOverflow post https://stackoverflow.com/questions/34198566/websocket-error-during-websocket-handshake-sent-non-empty-sec-websocket-proto
Daphne should handle that. so...
Are you able to put together a minimal project the recreates you issue? If so I can try to have a look...
Thanks for the response. Being that I got it working in IE and Firefox, I reckon the issue has to do with connecting via local host in chrome. I'm going to go live in a few days and see what's what, but if the issue persists, I will definitely take you up on your offer. Thanks, friend!
OK, I'll close this now. Happy to re-open if we can pin it down to an issue on Channels.
Hello. I'm having a similar issue. Apparently, a common hack for authenticating websockets with token authentication is to put the token in the subprotocol argument of the websocket connection. I've done this, with the following AuthMiddleware:
@database_sync_to_async
def validate_token(token):
auth = TokenAuthentication()
return auth.authenticate_credentials(token.encode("utf-8"))
@database_sync_to_async
def close_connections():
close_old_connections()
class WebsocketTokenAuthMiddleware:
def __init__(self, inner):
self.inner = inner
def __call__(self, scope):
close_connections()
try:
token = scope["subprotocols"][0]
scope["user"] = validate_token(token)
return self.inner(scope)
except Exception:
pass
This works fine on Firefox, but gives the same error as @jayalen86 was having on Chrome. This is running locally, via Daphne.
Short of some information as to _why_ this doesn't work on Chrome, I don't think there's anything we can say.
Happy to re-open if there's something specific that we can do.
I am having the same problem in Chrome, but not in Firefox and not in Safari.
Looks like Chrome expects to receive the response header sec-websocket-accept from the server.
https://stackoverflow.com/a/28046874
https://stackoverflow.com/questions/42357140/django-channels-how-to-respond-to-a-websocket-open-request-with-a-subprotocol/46582687
I found this issue where sending a response header is mentioned https://github.com/django/channels/issues/928#issuecomment-368180935
await self.send({"type": "websocket.accept", "subprotocol": "Sec-Websocket-Accept"})
but it doesn't seem to work. How can you send the response header sec-websocket-accept?
I hope this helps us figure where the problem is :)
Is there anything in the Autobahn docs or tests about this?
@carltongibson I haven鈥檛 checked those
I'm wondering if it shouldn't be handled at that level. Seems a bit low-level for us? 馃
I agree. Not all applications use that protocol so it shouldn鈥檛 be handled by the channels package in my opinion as well.
I still haven鈥檛 figured out how to send the response header Chrome expects to receive in order to accept the connection on the client side. Any help?
ok, I figured it out.
On the frontend, this is how I create a websocket:
const websocket = new WebSocket('ws://127.0.0.1:8000/ws/', ['Token', 'user_secret_token'])
This is my consumer:
class MyConsumer(JsonWebsocketConsumer):
def connect(self):
self.room_group_name = 'example_room'
# Join room group
async_to_sync(self.channel_layer.group_add)(self.room_group_name, self.channel_name)
# incorrect
# self.accept()
# correct
self.accept('Token')
@jayalen86 @alex-yobota hope this helps you! :)
Most helpful comment
ok, I figured it out.
On the frontend, this is how I create a websocket:
This is my consumer:
@jayalen86 @alex-yobota hope this helps you! :)