適用於 Azure Web PubSub 的 WebSocket 用戶端通訊協定
用戶端使用標準 WebSocket 通訊協定來連線到 Azure Web PubSub。
服務端點
Web PubSub 服務提供兩種端點供用戶端連線:
/client/hubs/{hub}
/client/?hub={hub}
{hub}
是必要參數,用以隔離不同的應用程式。 可以在路徑或查詢中設定。
授權
用戶端使用 JSON Web 權杖 (JWT) 來連線到服務。 權杖可以位於查詢字串 (例如 /client/?hub={hub}&access_token={token}
) 或 Authorization
標頭 (例如 Authorization: Bearer {token}
) 中。
以下是一般授權工作流程:
- 用戶端與應用程式伺服器交涉。 應用程式伺服器包含授權中介軟體,可處理用戶端要求,並簽署 JWT 讓用戶端連線至服務。
- 應用程式伺服器將 JWT 和服務 URL 傳回給用戶端。
- 用戶端使用從應用程式伺服器傳回的 URL 和 JWT,嘗試連線到 Web PubSub 服務。
簡單的 WebSocket 用戶端
顧名思義,簡單的 WebSocket 用戶端就是簡單的 WebSocket 連線。 也可以有自己的自訂子通訊協定。
例如,在 JavaScript 中,您可以使用下列程式碼來建立簡單的 WebSocket 用戶端:
// simple WebSocket client1
var client1 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1');
// simple WebSocket client2 with some custom subprotocol
var client2 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'custom.subprotocol')
PubSub WebSocket 用戶端
PubSub WebSocket 用戶端使用 Azure Web PubSub 服務所定義的子通訊協定:
json.webpubsub.azure.v1
protobuf.webpubsub.azure.v1
透過服務支援的子通訊協定,PubSub WebSocket 用戶端只要具有權限,就可以直接將訊息發佈至群組。
json.webpubsub.azure.v1
子通訊協定
建立 PubSub WebSocket 用戶端
var pubsubClient = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'json.webpubsub.azure.v1');
直接從用戶端加入群組
let ackId = 0;
pubsubClient.send(
JSON.stringify({
type: 'joinGroup',
group: 'group1',
ackId: ++ackId
}));
直接從用戶端將訊息傳送至群組
let ackId = 0;
pubsubClient.send(
JSON.stringify({
type: 'sendToGroup',
group: 'group1',
ackId: ++ackId,
dataType: "json",
data: {
"hello": "world"
}
}));
protobuf.webpubsub.azure.v1
子通訊協定
通訊協定緩衝區 (protobuf) 是一種語言中性、平台中性、二進位型的通訊協定,可簡化傳送二進位資料。 Protobuf 提供工具從許多語言產生用戶端,例如 JAVA、Python、Objective-C、C# 和 C++。 深入了解 protobuf。
例如,在 JavaScript 中,您可以使用下列程式碼建立採用 protobuf 子通訊協定的 PubSub WebSocket 用戶端:
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
AckId 和認可回應
PubSub WebSocket 用戶端支援 joinGroup
、leaveGroup
、sendToGroup
和 event
訊息使用 ackId
屬性。 使用 ackId
時,您可以在處理要求後收到認可回應訊息。 在射後不理情節中,您可以選擇省略 ackId
。 在本文中,我們說明指定或未指定 ackId
時的行為差異。
未指定 ackId
時的行為
如果未指定 ackId
,則為射後不理。 即使代理訊息時發生錯誤,您也無法收到通知。
指定 ackId
時的行為
等冪發佈
ackId
是 uint64 數字,且應該在具有相同連線識別碼的用戶端內是唯一的。Web PubSub 服務會記錄 ackId
,且具有相同 ackId
的訊息會視為相同訊息。 服務會拒絕多次代理相同的訊息,這在重試時很有用,可避免重複的訊息。 例如,如果用戶端傳送具有 ackId=5
的訊息,但無法接收具有 ackId=5
的認可回應,則用戶端會重試並再次傳送相同的訊息。 在某些情況下,已代理訊息,但認可回應因故遺失,此時服務會拒絕重試,並以 Duplicate
原因傳回認可回應。
認可回應
對於具有 ackId
的每個要求,Web PubSub 服務會傳送認可回應。
格式:
{
"type": "ack",
"ackId": 1, // The ack id for the request to ack
"success": false, // true or false
"error": {
"name": "Forbidden|InternalServerError|Duplicate",
"message": "<error_detail>"
}
}
ackId
與要求相關聯。success
是 bool,指出服務是否成功處理要求。 如果是false
,則用戶端必須檢查error
。只有當
success
為false
時,error
才存在,用戶端應該要有不同的邏輯來處理不同的name
。 您應該假設未來可能會有更多種name
。Forbidden
:用戶端對要求沒有權限。 用戶端必須新增相關的角色。InternalServerError
:服務中發生內部錯誤。 需要重試。Duplicate
:服務已處理具有相同ackId
的訊息。
權限
您在先前的 PubSub WebSocket 用戶端描述中可能注意到,用戶端只有在獲「授權」時,才能發佈至其他用戶端。 當用戶端正在連線或在連線的存留期內,可以授與用戶端的權限。
角色 | 權限 |
---|---|
未指定 | 用戶端可以傳送事件要求。 |
webpubsub.joinLeaveGroup |
用戶端可以加入或離開任何群組。 |
webpubsub.sendToGroup |
用戶端可以將訊息發佈至任何群組。 |
webpubsub.joinLeaveGroup.<group> |
用戶端可以加入或離開群組 <group> 。 |
webpubsub.sendToGroup.<group> |
用戶端可以將訊息發佈至群組 <group> 。 |
有幾種方式可以授與用戶端的權限:
1.產生存取權杖時,將角色指派給用戶端
用戶端可以使用 JWT 權杖來連線到服務,權杖承載可以攜帶資訊,例如用戶端的 role
。 簽署 JWT 權杖給用戶端時,您可以指定特定角色給用戶端,以授與用戶端的權限。
例如,讓我們簽署有權將訊息傳送至 group1
和 group2
的 JWT 權杖:
let token = await serviceClient.getClientAccessToken({
roles: [ "webpubsub.sendToGroup.group1", "webpubsub.sendToGroup.group2" ]
});
2.使用 connect
事件處理常式將角色指派給用戶端
註冊事件處理常式時 connect
,也可以設定用戶端的角色,而上游事件處理常式在處理 roles
事件時,可以將用戶端的 connect
傳回至 Web PubSub 服務。
例如,在 JavaScript 中,您可以設定 handleConnect
事件來這麼做:
let handler = new WebPubSubEventHandler("hub1", {
handleConnect: (req, res) => {
// auth the connection and set the userId of the connection
res.success({
roles: [ "webpubsub.sendToGroup.group1", "webpubsub.sendToGroup.group2" ]
});
},
});
3.在執行階段透過 REST API 或伺服器 SDK 將角色指派給用戶端
let service = new WebPubSubServiceClient("<your_connection_string>", "test-hub");
await service.grantPermission("<connection_id>", "joinLeaveGroup", { targetName: "group1" });
下一步
使用這些資源開始建置自己的應用程式: