![](/img/trans.png)
[英]How to pass request over Django channels WebSocket and call Django view
[英]Django Channels. How to respond to a WebSocket open request with a subprotocol?
在 JavaScript 中,浏览器可以指定一个子协议作为 WebSocket 创建中的第二个参数:
socket=new WebSocket(url, subprotocol)
使用 Chrome 进行试验,这将作为标头中的Sec-WebSocket-Protocol
元素正确发送到服务器。
使用 Django 频道,一个简单的消费者
def ws_add(message):
message.reply_channel.send({"accept": True,})
给出错误
与“xxx”的 WebSocket 连接失败:WebSocket 握手期间出错:发送了非空的“Sec-WebSocket-Protocol”标头,但未收到响应。
在 Django 频道的 ws_add 函数中接受该连接请求的正确方法是什么?
您必须指定要在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"})
我遇到了同样的问题。 Websocket 规范说,如果客户端请求子协议,那么服务器必须响应以让客户端知道它支持它。 在我的情况下,子协议是“graphql-ws”
在深入研究石墨烯代码后,最终发现这是将以下内容添加到设置中的简单案例:
CHANNELS_WS_PROTOCOLS = ["graphql-ws"]
因此,只需将协议列表替换为您想要支持的任何内容。 当然,一旦你这样做了,你实际上需要在服务器上实现子协议。
如果有人像我一样现在偶然发现这个问题,这是我解决它的方法:
当您像这样在消费者的 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 频道 2.4.0 Django 3.1.2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.