使用 HTTP 协议的 Azure Web PubSub 事件处理程序的 CloudEvents 扩展
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}
响应状态代码表示未成功时,连接将被删除。
后续步骤
使用这些资源开始生成自己的应用程序: