Django 频道。如何使用子协议响应 WebSocket 打开请求?
Django Channels. How to respond to a WebSocket open request with a subprotocol?
在 JavaScript 中,浏览器可以指定 sub-protocol 作为 WebSocket 创建中的第二个参数:
socket=new WebSocket(url, subprotocol)
使用 Chrome 进行试验,这会作为 header.
中的 Sec-WebSocket-Protocol
元素正确发送到服务器
使用Django通道,一个简单的消费者
def ws_add(message):
message.reply_channel.send({"accept": True,})
报错
WebSocket connection to 'xxx' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received.
在 Django 通道的 ws_add 函数中接受该连接请求的正确方法是什么?
我遇到了同样的问题。 Websocket 规范说,如果客户端请求子协议,则服务器必须响应让客户端知道它支持它。在我的例子中,子协议是 "graphql-ws"
在深入研究石墨烯代码后,最终发现将以下内容添加到设置中是一个简单的案例:
CHANNELS_WS_PROTOCOLS = ["graphql-ws"]
因此,只需将协议列表替换为您想要支持的任何协议即可。当然,一旦你完成了这个,你实际上需要在服务器上实现子协议。
您必须指定要在 websocket.accept
消息中使用的子协议。例如,如果您继承 channels.generic.websocket.WebsocketConsumer
(也适用于 SyncConsumer
)并使用 my-protocol
的 Sec-WebSocket-Protocol
:
class MyProtocolConsumer(WebsocketConsumer):
def websocket_connect(self, message):
self.base_send({"type": "websocket.accept", "subprotocol": "my-protocol"})
如果有人像我一样偶然发现这个问题,我是这样解决的:
当您在消费者的连接方法上调用 self.accept() 时,您需要添加您在前端使用的 websocket 协议(在我的例子中是令牌)作为子协议参数:
这是我在前端创建 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 频道 2.4.0
Django 3.1.2
在 JavaScript 中,浏览器可以指定 sub-protocol 作为 WebSocket 创建中的第二个参数:
socket=new WebSocket(url, subprotocol)
使用 Chrome 进行试验,这会作为 header.
中的Sec-WebSocket-Protocol
元素正确发送到服务器
使用Django通道,一个简单的消费者
def ws_add(message):
message.reply_channel.send({"accept": True,})
报错
WebSocket connection to 'xxx' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received.
在 Django 通道的 ws_add 函数中接受该连接请求的正确方法是什么?
我遇到了同样的问题。 Websocket 规范说,如果客户端请求子协议,则服务器必须响应让客户端知道它支持它。在我的例子中,子协议是 "graphql-ws"
在深入研究石墨烯代码后,最终发现将以下内容添加到设置中是一个简单的案例:
CHANNELS_WS_PROTOCOLS = ["graphql-ws"]
因此,只需将协议列表替换为您想要支持的任何协议即可。当然,一旦你完成了这个,你实际上需要在服务器上实现子协议。
您必须指定要在 websocket.accept
消息中使用的子协议。例如,如果您继承 channels.generic.websocket.WebsocketConsumer
(也适用于 SyncConsumer
)并使用 my-protocol
的 Sec-WebSocket-Protocol
:
class MyProtocolConsumer(WebsocketConsumer):
def websocket_connect(self, message):
self.base_send({"type": "websocket.accept", "subprotocol": "my-protocol"})
如果有人像我一样偶然发现这个问题,我是这样解决的:
当您在消费者的连接方法上调用 self.accept() 时,您需要添加您在前端使用的 websocket 协议(在我的例子中是令牌)作为子协议参数:
这是我在前端创建 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 频道 2.4.0 Django 3.1.2