繁体   English   中英

姜戈频道。 如何使用子协议响应 WebSocket 打开请求?

[英]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-protocolSec-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM