![](/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.