在JavaScript中,浏览器可以将子协议指定为WebSocket创建中的第二个参数:
socket=new WebSocket(url, subprotocol)
使用Chrome进行试验,可以将其作为标题中的Sec-WebSocket-Protocol
元素正确发送到服务器。
使用Django频道,一个简单的消费者
def ws_add(message):
message.reply_channel.send({"accept": True,})
给出错误
WebSocket连接到' xxx'失败:WebSocket握手期间出错:发送非空的Sec-WebSocket-Protocol'标题但未收到任何回复。
在Django频道中接受该连接请求的正确方法是什么? ws_add函数?
答案 0 :(得分:2)
我遇到了同样的问题。 Websocket规范说,如果客户端要求子协议,那么服务器必须响应让客户知道它支持它。在我的情况下,子协议是“graphql-ws”
在石墨烯代码中挖掘之后,最终发现在设置中添加以下内容是一个简单的例子:
CHANNELS_WS_PROTOCOLS = ["graphql-ws"]
因此,只需将协议列表替换为您要支持的任何内容即可。当然,一旦你完成了这个,你实际上需要在服务器上实现子协议。
答案 1 :(得分:2)
您必须在websocket.accept
消息中指定要使用的子协议。例如,如果您继承channels.generic.websocket.WebsocketConsumer
(也适用于SyncConsumer
)并使用Sec-WebSocket-Protocol
的{{1}}:
my-protocol
答案 2 :(得分:0)
如果现在有人像我一样偶然发现了这个问题,这就是我的解决方法:
当您在消费者的connect方法上调用self.accept()时,您需要添加前端使用的websocket协议(在本例中为Token)作为子协议参数:
这是我在前端创建websocket连接的方式:
const websocket = new WebSocket('ws://127.0.0.1:8000/ws/', ['Token', 'user_secret_token'])
这是我的consumers.py
的样子:
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')
Django Channels 2.4.0 Django 3.1.2