Azure Web PubSub イベント ハンドラーの CloudEvents 拡張機能と HTTP プロトコル
Web PubSub サービスは、CloudEvents HTTP プロトコル バインドを使用し、アップストリームの Webhook にクライアント イベントを配信します。
Web PubSub サービスからサーバーに送信されるデータは常に CloudEvents binary
形式です。
- Webhook の検証
- Web PubSub CloudEvents の属性の拡張
- イベント
- ブロック イベント
- 非ブロック イベント
Webhook の検証
Webhook の検証は、CloudEvents に従います。 要求のヘッダーには常に WebHook-Request-Origin: xxx.webpubsub.azure.com
が含まれます。
配信ターゲットでイベントの配信が許可されている場合にのみ、WebHook-Allowed-Origin
ヘッダーを含めることによって要求に応答する必要があります。次に例を示します。
WebHook-Allowed-Origin: *
または:
WebHook-Allowed-Origin: xxx.webpubsub.azure.com
現在、WebHook-Request-Rate と WebHook-Request-Callback はサポートされていません。
Web PubSub CloudEvents の属性の拡張
また、HTTP 仕様は似たパターンに従うようになっており、拡張 HTTP ヘッダーにプレフィックスとして X- が付いていないことも指摘されました。
この拡張機能では、Web PubSub によって生成されるすべてのイベントに使用される属性が定義されています。
属性
名前 | 種類 | 説明設定 | 例 |
---|---|---|---|
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)) のように値が計算されます。 上流では、要求を処理する前に、それが有効かどうかを確認する必要があります。 |
Events
イベントには 2 種類あります。 1 つは、サービスがイベントの応答を待ってから続行する "ブロック" イベントです。 もう 1 つは、サービスが次のメッセージを処理する前にイベントの応答を待たない "非ブロック" イベントです。
- ブロック イベント
- 非ブロック イベント
システム connect
イベント
ce-type
:azure.webpubsub.sys.connect
Content-Type
:application/json
要求の形式:
POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
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": "<certificate SHA-1 thumbprint>",
"content": "-----BEGIN CERTIFICATE-----\r\n...\r\n-----END CERTIFICATE-----"
}
]
}
成功応答の形式:
ヘッダー
ce-connectionState
: このヘッダーが存在する場合、この接続の接続状態はヘッダーの値に更新されます。 接続状態を更新できるのは "ブロック" イベントのみです。 次の例では、base64 でエンコードされた JSON 文字列を使用して、接続の複雑な状態を格納します。状態コード:
204
: 成功。コンテンツはありません。200
: 成功。コンテンツは JSON 形式である必要があり、次のプロパティが許可されます。subprotocols
connect
イベントによって、クライアントから上流にサブプロトコルと認証情報が転送されます。 Web PubSub サービスが状態コードを使用して、要求が WebSocket プロトコルにアップグレードされるかどうかを判断します。要求に
subprotocols
プロパティが含まれる場合、サーバーはサポートしている 1 つのサブプロトコルを返す必要があります。 サーバーでどのサブプロトコルも使用する必要がない場合は、応答でsubprotocol
プロパティを送信しないようにする必要があります。 空のヘッダーを送信することは無効です。userId
:{auth-ed user ID}
サービスでは匿名接続が許可されているので、サービスにクライアント接続のユーザー ID を通知するのは
connect
イベントの役割です。 応答ペイロードuserId
が存在する場合、サービスによってそこからユーザー ID が読み取られます。 要求のクレームからも、connect
イベントの応答ペイロードからも、ユーザー ID を読み取ることができない場合、接続は切断されます。groups
:{groups to join}
このプロパティにより、ユーザーがこの接続を 1 つ以上のグループに追加する便利な方法が提供されます。 これにより、この接続を何らかのグループに追加するために別の呼び出しを行う必要はありません。
roles
:{roles the client has}
このプロパティにより、アップストリーム Webhook でクライアントを承認するための方法が提供されます。 PubSub WebSocket クライアントの初期アクセス許可を付与するさまざまなロールがあります。 アクセス許可の詳細については、クライアントのアクセス許可に関する記事を参照してください。
HTTP/1.1 200 OK
ce-connectionState: eyJrZXkiOiJhIn0=
{
"groups": [],
"userId": "",
"roles": [],
"subprotocol": ""
}
エラー応答の形式:
4xx
: エラー。上流からの応答が、クライアント要求への応答として返されます。
HTTP/1.1 401 Unauthorized
システム connected
イベント
クライアントによる WebSocket ハンドシェイクが完了し、正常に接続されると、サービスによって上流が呼び出されます。
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.com
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.com
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.com
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
成功応答の形式
- status code
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.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>
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.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>
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.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>
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
- status code
204
: 成功。コンテンツはありません。200
: 成功。PubSub WebSocket クライアントに送信されるデータは、Content-Type
に依存します。
- ヘッダー
ce-connectionState
: このヘッダーが存在する場合、この接続の接続状態はヘッダーの値に更新されます。 接続状態を更新できるのは "ブロック" イベントのみです。 次の例では、base64 でエンコードされた JSON 文字列を使用して、接続の複雑な状態を格納します。 - ヘッダー
Content-Type
がapplication/octet-stream
の場合、サービスからクライアントにbinary
としてdataType
を使用してUserResponsePayload
が返送されます。ペイロードは base64 でエンコードされています。 応答のサンプル:{ "type": "message", "from": "server", "dataType": "binary", "data" : "aGVsbG8gd29ybGQ=" }
Content-Type
がtext/plain
の場合、サービスからクライアントにdataType
としてtext
を使用してUserResponsePayload
が送信されます。ペイロードは文字列です。Content-Type
がapplication/json
の場合、サービスからクライアントにdataType
=json
を使用してUserResponsePayload
が送信されます。応答のペイロードの本文はdata
値トークンです。
エラー応答の形式
状態コードが成功でない場合は、エラー応答と見なされます。 {custom_event}
応答状態コードが成功でない場合、接続は切断されます。
次のステップ
これらのリソースを使用して、独自のアプリケーションの構築を開始します。