CloudEvents-Erweiterung für Azure Web PubSub-Ereignishandler mit HTTP-Protokoll

Der Web PubSub-Dienst übergibt Clientereignisse mithilfe der CloudEvents-HTTP-Protokollbindung an den Upstream-Webhook.

Die Daten, die vom Web PubSub-Dienst an den Server gesendet werden, weisen immer das CloudEvents-Format binary auf.

Webhookvalidierung

Die Webhookvalidierung folgt CloudEvents. Die Anforderung enthält immer WebHook-Request-Origin: xxx.webpubsub.azure.com im Header.

Wenn und nur dann, wenn das Übermittlungsziel die Übermittlung der Ereignisse gestattet, MUSS es auf die Anforderung antworten, indem es den WebHook-Allowed-Origin-Header mit einschließt, z. B.:

WebHook-Allowed-Origin: *

Oder:

WebHook-Allowed-Origin: xxx.webpubsub.azure.com

Vorerst werden WebHook-Request-Rate und WebHook-Request-Callback nicht unterstützt.

Web PubSub CloudEvents-Attributerweiterung

Es wurde auch erwähnt, dass die HTTP-Spezifikation jetzt einem ähnlichen Muster folgt, d. h. es wird nicht mehr vorgeschlagen, dass Erweiterungs-HTTP-Headern das Präfix X- vorangestellt wird.

Diese Erweiterung definiert Attribute, die von der Web PubSub-Anwendung für jedes von ihr erzeugte Ereignis verwendet werden.

Attribute

Name Typ Beschreibung des Dataflows Beispiel
userId string Der Benutzer, für den die Verbindung authentifiziert wurde
hub string Der Hub, zu dem die Verbindung gehört
connectionId string Die connectionId ist für die Clientverbindung eindeutig definiert.
eventName string Der Name des Ereignisses ohne Präfix
subprotocol string Das Unterprotokoll, das der Client verwendet, sofern vorhanden.
connectionState string Legt den Status der Verbindung fest. Sie können denselben Antwort-Header verwenden, um den Wert des Status zurückzusetzen. Mehrere connectionState-Header sind nicht zulässig. Codieren Sie den Zeichenfolgenwert mit Base64, wenn er komplexe Zeichen enthält, z. B. base64(jsonString), um komplexe Objekte mit diesem Attribut übergeben.
signature string Die Signatur für den Upstreamwebhook, um zu überprüfen, ob die eingehende Anforderung vom erwarteten Ursprung stammt. Der Dienst berechnet den Wert mithilfe des primären Zugriffsschlüssels und des sekundären Zugriffsschlüssels als HMAC-Schlüssel: Hex_encoded(HMAC_SHA256(accessKey, connectionId)). Der Upstream sollte vor der Verarbeitung überprüfen, ob die Anforderung gültig ist.

Ereignisse

Es gibt zwei Arten von Ereignissen. Eine Art sind blockierende Ereignisse, d. h. der Dienst wartet und wird erst fortgesetzt, wenn die Antwort des Ereignisses vorliegt. Die andere Art sind nicht-blockierende Ereignisse, d. h. der Dienst wartet nicht auf die Antwort des Ereignisses, bevor die nächste Nachricht verarbeitet wird.

Systemconnectereignis

  • ce-type: azure.webpubsub.sys.connect
  • Content-Type: application/json

Anforderungsformat:

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": "ABC"
        }
    ]
}

Format der Antwort bei Erfolg:

  • Kopfzeile ce-connectionState: Wenn dieser Header existiert, wird der Verbindungsstatus dieser Verbindung auf den Wert des Headers aktualisiert. Nur blockierende Ereignisse können den Verbindungsstatus aktualisieren. Das folgende Beispiel verwendet einen base64-kodierten JSON-String, um den komplexen Status der Verbindung zu speichern.

  • Statuscode:

    • 204: Erfolg; ohne Inhalt.
    • 200: Erfolg; der Inhalt SOLLTE ein JSON-Format mit den folgenden zulässigen Eigenschaften aufweisen:
      • subprotocols

        Das connect-Ereignis gibt das Unterprotokoll und die Authentifizierungsinformationen an Upstream vom Client weiter. Der Web PubSub-Dienst verwendet den Statuscode, um zu bestimmen, ob die Anforderung auf das WebSocket-Protokoll aktualisiert wird.

        Wenn die Anforderung die Eigenschaft subprotocols enthält, sollte der Server ein von ihm unterstütztes Unterprotokoll zurückgeben. Wenn der Server keine Unterprotokolle verwenden möchte, sollte er die subprotocol-Eigenschaft nicht als Antwort senden. Das Senden eines leeren Headers ist ungültig.

      • userId: {auth-ed user ID}

        Da der Dienst anonyme Verbindungen zulässt, liegt es in der Verantwortung des connect Ereignisses, dem Dienst die Benutzer-ID der Clientverbindung mitzuteilen. Der Dienst liest die Benutzer-ID aus den Antwortnutzdaten userId, sofern diese existiert. Die Verbindung wird getrennt, wenn die Benutzer-ID weder aus den Anforderungsansprüchen noch aus der Antwortnutzdaten des connect-Ereignisses gelesen werden kann.

      • groups: {groups to join}

        Die Eigenschaft bietet dem Benutzer eine praktische Möglichkeit, diese Verbindung zu einer oder mehreren Gruppen hinzuzufügen. Auf diese Weise ist kein weiterer Aufruf erforderlich, um diese Verbindung zu einer Gruppe hinzuzufügen.

      • roles: {roles the client has}

        Die Eigenschaft bietet dem Upstream-Webhook eine Möglichkeit, den Client zu autorisieren. Für PubSub WebSocket-Clients gibt es verschiedene Rollen, um anfängliche Berechtigungen zu erteilen. Weitere Informationen zu den Berechtigungen finden Sie unter Clientberechtigungen.

HTTP/1.1 200 OK
ce-connectionState: eyJrZXkiOiJhIn0=

{
    "groups": [],
    "userId": "",
    "roles": [],
    "subprotocol": ""
}

Format von Fehlerantworten:

  • 4xx: Fehler; die Antwort von Upstream wird als Antwort für die Clientanforderung zurückgegeben.
HTTP/1.1 401 Unauthorized

Systemconnectedereignis

Der Dienst ruft Upstream auf, wenn der Client den WebSocket-Handshake abschließt und erfolgreich verbunden ist.

  • ce-type: azure.webpubsub.sys.connected
  • Content-Type: application/json
  • ce-connectionState: eyJrZXkiOiJhIn0=

Der Anforderungstext ist ein leerer JSON-Code.

Anforderungsformat:

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=

{}

Antwortformat:

2xx: Antwort bei Erfolg

connected ist ein asynchrones Ereignis. Wenn der Antwortstatuscode nicht erfolgreich ist, protokolliert der Dienst einen Fehler.

HTTP/1.1 200 OK

Systemdisconnectedereignis

Das disconnected-Ereignis wird immer ausgelöst, wenn die Clientanforderung abgeschlossen wird, falls das connectEreignis (Verbinden) den Statuscode 2xx zurückgibt.

  • ce-type: azure.webpubsub.sys.disconnected
  • Content-Type: application/json

Anforderungsformat:

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 beschreibt den Grund für die getrennten Clientverbindungen.

Antwortformat:

2xx: Antwort bei Erfolg

disconnected ist ein asynchrones Ereignis. Wenn der Antwortstatuscode nicht erfolgreich ist, protokolliert der Dienst einen Fehler.

HTTP/1.1 200 OK

Benutzerereignis message für einfache WebSocket-Clients

Der Dienst ruft den Ereignishandler upstream für jeden WebSocket-Nachrichtenframe auf.

  • ce-type: azure.webpubsub.user.message
  • Content-Type: application/octet-stream für binären Frame; text/plain für Textframe;

UserPayload ist das, was der Client sendet.

Anforderungsformat:

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

Format der Antwort bei Erfolg

  • Statuscode
    • 204: Erfolg; ohne Inhalt.
    • 200: Erfolg; das Format von UserResponsePayload hängt von Content-Type der Antwort ab.
  • Content-Type: application/octet-stream für binären Frame; text/plain für Textframe;
  • Kopfzeile Content-Type: application/octet-stream für Binärrahmen; text/plain für Textrahmen;
  • Kopfzeile ce-connectionState: Wenn dieser Header existiert, wird der Verbindungsstatus dieser Verbindung auf den Wert des Headers aktualisiert. Nur blockierende Ereignisse können den Verbindungsstatus aktualisieren. Das folgende Beispiel verwendet einen base64-kodierten JSON-String, um den komplexen Status der Verbindung zu speichern.

Wenn Content-Typeapplication/octet-stream ist, sendet der Dienst UserResponsePayload mithilfe des binary WebSocket-Frames an den Client. Wenn Content-Typetext/plain ist, sendet der Dienst UserResponsePayload mithilfe des text WebSocket-Frames an den Client.

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

Format von Fehlerantworten

Wenn der Statuscode nicht „Erfolg“ lautet, wird er als Fehlerantwort betrachtet. Die Verbindung wird getrennt, wenn der Antwortstatuscode message nicht „Erfolg“ lautet.

Benutzerdefiniertes Ereignis {custom_event} für PubSub WebSocket-Clients

Der Dienst ruft den Ereignishandler-Webhook für jede gültige benutzerdefinierte Ereignismeldung auf.

Fall 1: Ereignis mit Textdaten versenden:

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

Was der Upstream-Ereignishandler empfängt (siehe unten). Der Content-Type der CloudEvents-HTTP-Anforderung ist text/plain für dataType=text.

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

Fall 2: Ereignis mit JSON-Daten versenden:

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

Was der Upstream-Ereignishandler empfängt (siehe unten). Der Content-Type der CloudEvents-HTTP-Anforderung ist application/json für dataType=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"
}

Fall 3: Ereignis mit Binärdaten versenden:

{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "binary",
    "data": "aGVsbG8gd29ybGQ=" // base64 encoded binary
}

Was der Upstream-Ereignishandler empfängt (siehe unten). Der Content-Type der CloudEvents-HTTP-Anforderung ist application/octet-stream für dataType=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>
ce-subprotocol: json.webpubsub.azure.v1

<binary data>

Format der Antwort bei Erfolg

HTTP/1.1 200 OK
Content-Type: application/octet-stream | text/plain | application/json
Content-Length: nnnn

UserResponsePayload
  • Statuscode
    • 204: Erfolg; ohne Inhalt.
    • 200: Erfolg; daten, die an den PubSub WebSocket-Client gesendet werden, hängen von Content-Type ab.
  • Kopfzeile ce-connectionState: Wenn dieser Header existiert, wird der Verbindungsstatus dieser Verbindung auf den Wert des Headers aktualisiert. Nur blockierende Ereignisse können den Verbindungsstatus aktualisieren. Das folgende Beispiel verwendet einen base64-kodierten JSON-String, um den komplexen Status der Verbindung zu speichern.
  • Wenn Kopfzeile Content-Type gleich application/octet-stream ist, sendet der Dienst UserResponsePayload unter Verwendung von dataType als binary mit base64-kodierter Nutzlast an den Client zurück. Eine Beispielantwort:
    {
        "type": "message",
        "from": "server",
        "dataType": "binary",
        "data" : "aGVsbG8gd29ybGQ="
    }
    
  • Wenn Content-Typetext/plain ist, sendet der Dienst mit der Nutzdatenzeichenfolge UserResponsePayload mit dataType als text an den Client.
  • Wenn Content-Typeapplication/json ist, sendet der Dienst mit data-Werttoken als Antwortnutzdatenkörper UserResponsePayload mit dataType=json an den Client.

Format von Fehlerantworten

Wenn der Statuscode nicht „Erfolg“ lautet, wird er als Fehlerantwort betrachtet. Die Verbindung wird getrennt, wenn der Antwortstatuscode {custom_event} nicht „Erfolg“ lautet.

Nächste Schritte

Erstellen Sie mithilfe dieser Ressourcen Ihre eigene Anwendung: