Azure Web PubSub 支持的 JSON WebSocket 子协议

使用 JSON WebSocket 子协议 json.webpubsub.azure.v1,可以通过服务在客户端之间交换发布/订阅消息,而无需往返访问上游服务器。 使用 json.webpubsub.azure.v1 子协议的 WebSocket 连接称为 PubSub WebSocket 客户端。

概述

简单 WebSocket 连接在发送消息时会触发 message 事件,并依赖于服务器端处理消息以及执行其他操作。

使用 json.webpubsub.azure.v1 子协议,可以创建具有以下功能的 PubSub WebSocket 客户端:

例如,可以使用以下 JavaScript 代码创建 PubSub WebSocket 客户端:

// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'json.webpubsub.azure.v1');

本文档介绍子协议 json.webpubsub.azure.v1 的请求和响应。 传入和传出数据帧都必须包含 JSON 有效负载。

权限

PubSub WebSocket 客户端只有在获得授权后才能发布到其他客户端。 分配给客户端的 roles 决定了授予给客户端的权限:

角色 权限
未指定 客户端可以发送事件请求。
webpubsub.joinLeaveGroup 客户端可以加入/退出任何组。
webpubsub.sendToGroup 客户端可以向任何组发布消息。
webpubsub.joinLeaveGroup.<group> 客户端可以加入/退出 <group> 组。
webpubsub.sendToGroup.<group> 客户端可以向 <group> 组发布消息。

服务器可通过 REST API 或服务器 SDK 动态授予或撤销客户端权限。

请求

加入组

格式:

{
    "type": "joinGroup",
    "group": "<group_name>",
    "ackId" : 1
}

退出组

格式:

{
    "type": "leaveGroup",
    "group": "<group_name>",
    "ackId" : 1
}

发布消息

格式:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "ackId" : 1,
    "noEcho": true|false,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId 是每个请求的标识,应具有唯一性。 该服务发送 ack 响应消息以通知请求的进程结果。 有关详细信息,请参阅 AckId 和 Ack 响应
  • noEcho 是可选项。 如果设置为 true,则不会将此消息回显到相同的连接。 如果未设置,则默认值为 false。
  • dataType 可设置为 jsontextbinary
    • jsondata 可以是 JSON 支持的任何类型,并且将按原样发布;如果未指定 dataType,则默认为 json
    • textdata 应为字符串格式,并且将发布字符串数据;
    • binarydata 应采用 base64 格式,并且将发布二进制数据;

案例 1:发布文本数据:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "text",
    "data": "text data",
    "ackId": 1
}
  • <group_name> 中的子协议客户端接收:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "text",
    "data" : "text data"
}
  • <group_name> 中的简单 WebSocket 客户端接收字符串 text data

案例 2:发布 JSON 数据:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    }
}
  • <group_name> 中的子协议客户端接收:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "json",
    "data" : {
        "hello": "world"
    }
}
  • <group_name> 中的简单 WebSocket 客户端接收序列化字符串 {"hello": "world"}

案例 3:发布二进制数据:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "binary",
    "data": "<base64_binary>",
    "ackId": 1
}
  • <group_name> 中的子协议客户端接收:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "binary",
    "data" : "<base64_binary>", 
}
  • <group_name> 中的简单 WebSocket 客户端接收二进制帧中的二进制数据。

发送自定义事件

格式:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}

dataType 可以是 textbinaryjson 之一:

  • json:数据可以是 json 支持的任何类型,将按原样发布;默认值为 json
  • text:数据采用字符串格式,将发布字符串数据;
  • binary:数据采用 base64 格式,将发布二进制数据;

案例 1:发送包含文本数据的事件:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "text",
    "data": "text data", 
}

上游事件处理程序接收如下所示的数据:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

text data

dataTypetext 时,CloudEvents HTTP 请求的 Content-Typetext/plain

案例 2:发送包含 JSON 数据的事件:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json",
    "data": {
        "hello": "world"
    }, 
}

上游事件处理程序接收如下所示的数据:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

{
    "hello": "world"
}

dataTypejson 时,CloudEvents HTTP 请求的 Content-Typeapplication/json

案例 3:发送包含二进制数据的事件:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "binary",
    "data": "base64_binary", 
}

上游事件处理程序接收如下所示的数据:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

binary

dataTypebinary 时,CloudEvents HTTP 请求的 Content-Typeapplication/octet-stream。 对于文本消息帧,WebSocket 帧可以是 text 格式,对于 binary 消息帧,可以是 UTF8 编码的二进制数据。

如果消息与所述格式不匹配,Web PubSub 服务将拒绝客户端。

Ping

格式:

{
    "type": "ping",
}

客户端可以向服务发送 ping 消息,以使 Web PubSub 服务能够检测客户端的运行情况。

响应

客户端接收的消息类型可以是:

  • 确认 - 对包含 ackId 的请求的响应。
  • 消息 - 来自组或服务器的消息。
  • 系统 - 来自 Web PubSub 服务的消息。

确认响应

如果客户端请求包含 ackId,则服务将为该请求返回确认响应。 客户端应处理确认机制:使用 async await 操作等待确认响应,如果在特定时间段内未收到确认响应,则使用超时操作。

格式:

{
    "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>"
    }
}

客户端实现始终应首先检查 successtrue 还是 false,然后仅在 successfalse 时才读取错误。

消息响应

客户端可以接收从其加入的组或者从服务器(以服务器管理角色运行,可将消息发送到特定的客户端或用户)发布的消息。

  1. 当消息来自组时

    {
        "type": "message",
        "from": "group",
        "group": "<group_name>",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
        "fromUserId": "abc"
    }
    
  2. 当消息来自服务器时,

    {
        "type": "message",
        "from": "server",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
    }
    

案例 1:通过 REST API 使用 Content-Type=text/plain 将数据 Hello World 发送到连接

  • 简单 WebSocket 客户端接收包含数据的文本 WebSocket 帧:Hello World

  • PubSub WebSocket 客户端接收:

    {
        "type": "message",
        "from": "server",
        "dataType" : "text",
        "data": "Hello World", 
    }
    

案例 2:通过 REST API 使用 Content-Type=application/json 将数据 { "Hello" : "World"} 发送到连接

  • 简单 WebSocket 客户端接收包含字符串式数据的文本 WebSocket 帧:{ "Hello" : "World"}

  • PubSub WebSocket 客户端接收:

    {
        "type": "message",
        "from": "server",
        "dataType" : "json",
        "data": {
            "Hello": "World"
        }
    }
    

如果 REST API 使用 application/json 内容类型发送字符串 Hello World,则简单 WebSocket 客户端将接收一个 JSON 字符串,即括在双引号 (") 中的 "Hello World"

案例 3:通过 REST API 使用 Content-Type=application/octet-stream 将二进制数据发送到连接

  • 简单 WebSocket 客户端接收包含二进制数据的二进制 WebSocket 帧。

  • PubSub WebSocket 客户端接收:

    {
        "type": "message",
        "from": "server",
        "dataType" : "binary",
        "data": "<base64_binary>"
    }
    

系统响应

Web PubSub 服务将系统相关的消息发送到客户端。

Pong 响应

Web PubSub 服务从客户端收到 ping 消息时会向客户端发送 pong 消息。

格式:

{
    "type": "pong",
}

连续

当客户端成功连接时发送到客户端的消息:

{
    "type": "system",
    "event": "connected",
    "userId": "user1",
    "connectionId": "abcdefghijklmnop",
}

已断开连接

当服务器关闭连接或者当服务拒绝客户端时发送到客户端的消息。

{
    "type": "system",
    "event": "disconnected",
    "message": "reason"
}

后续步骤

使用这些资源开始生成自己的应用程序: