簡體   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