Web PubSub 服务使用 CloudEvents HTTP 协议绑定将客户端事件传送到上游 Webhook。
从 Web PubSub 服务发送到服务器的数据一律采用 CloudEvents binary 格式。
- Webhook 验证
- Web PubSub CloudEvents 属性扩展
- 事件
- 阻塞事件
- 非阻塞事件
 
Webhook 验证
Webhook 验证遵循 CloudEvents。 请求的标头中始终包含 WebHook-Request-Origin: xxx.webpubsub.azure.cn。
当且仅当传送目标允许传送事件时,在答复请求时必须包含 WebHook-Allowed-Origin 标头,例如:
WebHook-Allowed-Origin: *
或:
WebHook-Allowed-Origin: xxx.webpubsub.azure.cn
目前,不支持 WebHook-Request-Rate 和 WebHook-Request-Callback。
Web PubSub CloudEvents 属性扩展
另请注意,HTTP 规范现在遵循类似的模式,不再建议扩展 HTTP 标头以 X- 作为前缀。
此扩展插件为它生成的每个事件定义 Web PubSub 使用的属性。
属性
| 名称 | Type | 说明 | 示例 | 
|---|---|---|---|
| userId | string | 连接通过身份验证的用户 | |
| hub | string | 连接所属于的中心 | |
| connectionId | string | connectionId 对于客户端连接是唯一的 | |
| eventName | string | 不带前缀的事件名称 | |
| subprotocol | string | 客户端使用的子协议(如果有) | |
| connectionState | string | 定义连接的状态。 你可以使用相同的响应头来重置状态值。 不允许使用多个 connectionState头。 如果字符串值内部包含复杂字符,则可对其进行 base64 编码,例如,使用此属性通过base64(jsonString)传递复杂对象。 | |
| signature | string | 上游 Webhook 的签名,用于验证传入请求是否来自预期来源。 该服务在计算值时使用主访问密钥和辅助访问密钥作为 HMAC密钥:Hex_encoded(HMAC_SHA256(accessKey, connectionId))。 上游应在处理请求之前检查请求是否有效。 | 
事件
有两种类型的事件。 一种是阻塞事件,服务等待这种事件的响应以继续后续步骤。 一种是非阻塞事件,服务在处理下一条消息之前,不会等待此类事件的响应。
- 阻塞事件
- 非阻塞事件
系统 connect 事件
- ce-type:- azure.webpubsub.sys.connect
- Content-Type:- application/json
请求格式:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.connect
ce-source: /hubs/{hub}/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}
ce-eventName: connect
{
    "claims": {},
    "query": {},
    "headers": {},
    "subprotocols": [],
    "clientCertificates": [
        {
            "thumbprint": "ABC"
        }
    ]
}
成功响应格式:
- ce-connectionState标头:如果此标头存在,则此连接的连接状态将更新为标头的值。 只有阻塞事件可以更新连接状态。 下面的示例使用 base64 编码的 JSON 字符串存储连接的复杂状态。
- 状态代码: - 204:成功,无内容。
- 200:成功后,内容应为 JSON 格式,允许以下属性:- subprotocols- connect事件将子协议和身份验证信息从客户端转发到 Upstream。 Web PubSub 服务使用状态码来确定请求是否将升级为 WebSocket 协议。- 如果请求包含 - subprotocols属性,则服务器应返回它支持的一个子协议。 如果服务器不想使用任何子协议,则不应在响应中发送- subprotocol属性。 发送空白标头无效。
- userId:- {auth-ed user ID}- 由于服务允许匿名连接,因此 - connect事件负责向服务告知客户端连接的用户 ID。 服务会从响应有效负载- userId中读取用户 ID(如果存在)。 如果从请求声明和- connect事件的响应有效负载中均无法读取用户 ID,连接会被删除。
- groups:- {groups to join}- 此属性为用户提供了一种将此连接添加到一个或多个组的简便方法。 这样,在将此连接添加到某个组时无需再进行另一次调用。 
- roles:- {roles the client has}- 该属性为上游 Webhook 提供了一种授权客户端的方法。 有不同的角色可以为 PubSub WebSocket 客户端授予初始权限。 有关权限的详细信息,请参阅客户端权限。 
 
 
HTTP/1.1 200 OK
ce-connectionState: eyJrZXkiOiJhIn0=
{
    "groups": [],
    "userId": "",
    "roles": [],
    "subprotocol": ""
}
错误响应格式:
- 4xx:错误,来自 Upstream 的响应将返回为客户端请求的响应。
HTTP/1.1 401 Unauthorized
系统 connected 事件
当客户端完成 WebSocket 握手并成功连接时,服务将调用 Upstream。
- ce-type:- azure.webpubsub.sys.connected
- Content-Type:- application/json
- ce-connectionState:- eyJrZXkiOiJhIn0=
请求正文为空 JSON。
请求格式:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.connected
ce-source: /hubs/{hub}/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}
ce-eventName: connected
ce-subprotocol: abc
ce-connectionState: eyJrZXkiOiJhIn0=
{}
响应格式:
2xx:成功响应。
connected 是一个异步事件,当响应状态代码表示未成功时,服务将记录一条错误。
HTTP/1.1 200 OK
系统 disconnected 事件
如果 connect 事件返回了 2xx 状态代码,则在客户端请求完成时,将始终会触发 disconnected 事件。
- ce-type:- azure.webpubsub.sys.disconnected
- Content-Type:- application/json
请求格式:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.disconnected
ce-source: /hubs/{hub}/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}
ce-eventName: disconnected
ce-subprotocol: abc
ce-connectionState: eyJrZXkiOiJhIn0=
{
    "reason": "{Reason}"
}
- reason- reason描述了客户端断开连接的原因。
响应格式:
2xx:成功响应。
disconnected 是一个异步事件,当响应状态代码表示未成功时,服务将记录一条错误。
HTTP/1.1 200 OK
简单 WebSocket 客户端的用户事件 message
该服务针对每个 WebSocket 消息帧在上游调用事件处理程序。
- ce-type:- azure.webpubsub.user.message
- Content-Type:- application/octet-stream表示二进制帧;- text/plain表示文本帧;
UserPayload 是客户端发送的内容。
请求格式:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
Content-Type: application/octet-stream | text/plain | application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.message
ce-source: /hubs/{hub}/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}
ce-eventName: message
ce-connectionState: eyJrZXkiOiJhIn0=
UserPayload
成功响应格式
- 状态代码 - 204:成功,无内容。
- 200:成功,- UserResponsePayload的格式取决于响应的- Content-Type。
 
- Content-Type:- application/octet-stream表示二进制帧;- text/plain表示文本帧;
- Content-Type标头:- application/octet-stream表示二进制帧;- text/plain表示文本帧;
- ce-connectionState标头:如果此标头存在,则此连接的连接状态将更新为标头的值。 只有阻塞事件可以更新连接状态。 下面的示例使用 base64 编码的 JSON 字符串存储连接的复杂状态。
当 Content-Type 为 application/octet-stream 时,服务使用 binary WebSocket 帧向客户端发送 UserResponsePayload。 当 Content-Type 为 text/plain 时,服务使用 text WebSocket 帧向客户端发送 UserResponsePayload。
HTTP/1.1 200 OK
Content-Type: application/octet-stream (for binary frame) or text/plain (for text frame)
Content-Length: nnnn
ce-connectionState: eyJrZXkiOiJhIn0=
UserResponsePayload
错误响应格式
当状态代码表示未成功时,将其被视为错误响应。 如果 message 响应状态代码表示未成功时,连接将被删除。
PubSub WebSocket 客户端的用户自定义事件 {custom_event}
服务针对每个有效的自定义事件消息调用事件处理程序 Webhook。
案例 1:发送包含文本数据的事件:
{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "text",
    "data": "text data"
}
上游事件处理程序的内容如下所示,对于 dataType=text,CloudEvents HTTP 请求的 Content-Type 为 text/plain
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
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>
ce-subprotocol: json.webpubsub.azure.v1
ce-connectionState: eyJrZXkiOiJhIn0=
text data
案例 2:发送包含 JSON 数据的事件:
{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    },
}
上游事件处理程序的内容如下所示,对于 dataType=json,CloudEvents HTTP 请求的 Content-Type 为 application/json
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
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>
ce-subprotocol: json.webpubsub.azure.v1
ce-connectionState: eyJrZXkiOiJhIn0=
{
    "hello": "world"
}
案例 3:发送包含二进制数据的事件:
{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "binary",
    "data": "aGVsbG8gd29ybGQ=" // base64 encoded binary
}
上游事件处理程序的内容如下所示,对于 dataType=binary,CloudEvents HTTP 请求的 Content-Type 为 application/octet-stream
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.cn
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>
ce-subprotocol: json.webpubsub.azure.v1
<binary data>
成功响应格式
HTTP/1.1 200 OK
Content-Type: application/octet-stream | text/plain | application/json
Content-Length: nnnn
UserResponsePayload
- 状态代码 - 204:成功,无内容。
- 200:成功,发送到 PubSub WebSocket 客户端的数据依赖于- Content-Type;
 
- ce-connectionState标头:如果此标头存在,则此连接的连接状态将更新为标头的值。 只有阻塞事件可以更新连接状态。 下面的示例使用 base64 编码的 JSON 字符串存储连接的复杂状态。
- 当 Content-Type标头为application/octet-stream时,服务在将UserResponsePayload发送回客户端时将使用dataType作为binary,并且有效负载采用 base64 编码。 示例响应:{ "type": "message", "from": "server", "dataType": "binary", "data" : "aGVsbG8gd29ybGQ=" }
- 当 Content-Type为text/plain时,服务在将UserResponsePayload发送到客户端时将使用dataType作为text,并且有效负载为字符串。
- 当 Content-Type为application/json时,服务在将UserResponsePayload发送到客户端时将使用dataType=json,后者以data值令牌作为响应有效负载正文。
错误响应格式
当状态代码表示未成功时,将其被视为错误响应。 如果 {custom_event} 响应状态代码表示未成功时,连接将被删除。
后续步骤
使用这些资源开始生成自己的应用程序: