Azure Web PubSub unterstütztes JSON-WebSocket-Unterprotokoll

Das JSON WebSocket-Unterprotocol ermöglicht json.webpubsub.azure.v1den Austausch von Veröffentlichungs-/Abonnieren-Nachrichten zwischen Clients über den Dienst ohne Roundtrip zum Upstreamserver. Eine WebSocket-Verbindung mit dem json.webpubsub.azure.v1 Unterprotocol wird als PubSub WebSocket-Client bezeichnet.

Übersicht

Eine einfache WebSocket-Verbindung löst ein message Ereignis aus, wenn es Nachrichten sendet und auf der Serverseite zum Verarbeiten von Nachrichten und anderen Vorgängen basiert.

Mit dem json.webpubsub.azure.v1 Unterprotocol können Sie PubSub WebSocket-Clients erstellen, die:

Sie können beispielsweise einen PubSub WebSocket-Client mit dem folgenden JavaScript-Code erstellen:

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

In diesem Dokument werden die Unterprotocolanforderungen json.webpubsub.azure.v1 und -antworten beschrieben. Sowohl eingehende als auch ausgehende Datenframes müssen JSON-Nutzlasten enthalten.

Berechtigungen

Ein PubSub-WebSocket-Client kann nur dann auf anderen Clients veröffentlichen, wenn er dazu autorisiert ist. Die dem Client zugewiesenen roles bestimmen die Berechtigungen, die dem Client gewährt werden:

Role Berechtigung
Nicht angegeben Der Client kann Ereignisanforderungen senden.
webpubsub.joinLeaveGroup Der Client kann einer beliebigen Gruppe beitreten/diese verlassen.
webpubsub.sendToGroup Der Client kann Nachrichten in einer beliebigen Gruppe veröffentlichen.
webpubsub.joinLeaveGroup.<group> Der Client kann der Gruppe <group> beitreten/diese verlassen.
webpubsub.sendToGroup.<group> Der Client kann Nachrichten in der Gruppe <group> veröffentlichen.
webpubsub.joinLeaveGroups.<pattern> Der Client kann jeder Gruppe beitreten/verlassen, deren Namen übereinstimmen <pattern> (siehe Rollenmuster für Wildcard-Gruppen).
webpubsub.sendToGroups.<pattern> Der Client kann Nachrichten in jeder Gruppe veröffentlichen, deren Namen übereinstimmen <pattern> (siehe Rollenmuster für Wildcardgruppen).

Der Server kann dynamisch Clientberechtigungen über REST-APIs oder Server-SDKs erteilen oder widerrufen.

Hinweis

Wildcardrollen (z. B. webpubsub.sendToGroups.<pattern>) werden während der Laufzeit nicht in REST-APIs oder Server-SDKs unterstützt.

Requests

Gruppen beitreten

Format:

{
    "type": "joinGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

Gruppen verlassen

Format:

{
    "type": "leaveGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

Veröffentlichen von Nachrichten

Format:

{
    "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 ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort
  • noEcho ist optional. Wenn dies auf „true“ festgelegt ist, wird diese Nachricht nicht an dieselbe Verbindung zurückgesendet. Wenn keine Festlegung erfolgt, ist der Standardwert FALSE.
  • dataType kann auf json, text oder binary festgelegt werden.
    • json: data kann ein beliebiger Typ sein, der von JSON unterstützt und in seinem jeweiligen Zustand veröffentlicht wird. Wenn dataType nicht angegeben ist, wird dieser Wert standardmäßig auf json festgelegt.
    • text: data sollte im Zeichenfolgenformat vorliegen, und die Zeichenfolgendaten werden veröffentlicht.
    • binary: data sollte im Base64-Format vorliegen, und die Binärdaten werden veröffentlicht.

Fall 1: Veröffentlichen von Textdaten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "text",
    "data": "text data",
    "ackId": 1
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "text",
    "data" : "text data"
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die Zeichenfolge text data.

Fall 2: Veröffentlichen von JSON-Daten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    }
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "json",
    "data" : {
        "hello": "world"
    }
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die serialisierte Zeichenfolge {"hello": "world"}.

Fall 3: Veröffentlichen von Binärdaten:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "binary",
    "data": "<base64_binary>",
    "ackId": 1
}
  • Die Unterprotokollclients in <group_name> empfangen:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "binary",
    "data" : "<base64_binary>", 
}
  • Die einfachen WebSocket-Clients in <group_name> empfangen die binären Daten im binären Frame.

Beginnen Sie mit dem Streamen von Nachrichten

Um einen Gruppenstream zu starten, senden Sie eine sendToGroup Anfrage mit der Eigenschaft stream . Eine Stream-Startanfrage enthält datanicht , dataType, oder ackId.

Format:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "noEcho": true|false,
    "stream": {
        "streamId": "<stream_id>",
        "idleTimeoutMs": 300000
    }
}
  • stream.streamId ist der Identifikator des logischen Stroms. Es muss ein nicht-leerer String sein und unter aktiven Streams auf derselben Clientverbindung eindeutig sein. Client-Bibliotheken werden empfohlen, um einen global eindeutigen Wert zu erzeugen, wie zum Beispiel einen GUID oder UUID.
  • stream.idleTimeoutMs ist optional. Wenn angegeben, muss sie größer als 0sein. Wenn weggelassen, ist der Dienststandard Millisekunden 300000 . Der Wert ist ein Leerlauf-Timeout, nicht die gesamte Lebensdauer des Stroms. Stream-Daten senden, einen Stream am Leben halten oder den Stream beenden, bevor dieser Timeout abläuft, wenn die Anwendung den Stream offen halten muss.
  • noEcho ist optional. Wenn sie auf true gesetzt sind, werden Stream-Nachrichten nicht an dieselbe Verbindung zurückgesendet. Wenn keine Festlegung erfolgt, ist der Standardwert FALSE.

Wenn der Strom akzeptiert wird, erhält der Client eine Stream-Ack-Antwort mit expectedSequenceId gesetzt auf 1.

Senden Sie Streaming-Daten

Um Stromdaten zu senden, senden Sie eine streamData Anfrage mit streamId, streamSequenceId, dataType, und data.

Format:

{
    "type": "streamData",
    "streamId": "<stream_id>",
    "streamSequenceId": 1,
    "dataType" : "json|text|binary",
    "data": {}
}
  • streamId identifiziert einen aktiven Stream auf derselben Client-Verbindung.
  • streamSequenceId ist eine positive uint64-Zahl. Das erste Datenfragment in einem Strom verwendet 1, und jedes folgende Datenfragment für dasselbe streamId nimmt genau 1zu.
  • dataTypekann mit jsondenselben Datenkodierungsregeln wie Publishing-Nachrichten auf , text, oder binarygesetzt werden.

Um einen Strom aktiv zu halten, ohne Daten an Abonnenten zu liefern, senden Sie eine streamData Anfrage mit nur type und streamId.

{
    "type": "streamData",
    "streamId": "<stream_id>"
}

Ende der Streaming-Nachrichten

Um einen Stream zu beenden, senden Sie eine streamEnd Anfrage.

Format:

{
    "type": "streamEnd",
    "streamId": "<stream_id>"
}

Um einen Strom mit einem von der Anwendung definierten Fehler zu beenden, fügen Sie die optionale error Eigenschaft hinzu.

{
    "type": "streamEnd",
    "streamId": "<stream_id>",
    "error": {
        "message": "<error_detail>",
        "userErrorCode": "<application_error_code>"
    }
}
  • error.message ist eine optionale, menschenlesbare Fehlermeldung.
  • error.userErrorCode ist ein optionaler, von der Anwendung definierter Fehlercode.

Wenn der Stream geschlossen wird, erhält der Publisher eine Stream geschlossen-Antwort.

Versenden von benutzerdefinierten Ereignissen

Format:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId ist die Identität jeder Anforderung und sollte eindeutig sein. Der Dienst sendet eine ack-Antwortnachricht, um den Prozess über das Ergebnis der Anforderung zu informieren. Ausführliche Informationen finden Sie unter AckId- and Ack-Antwort

dataType kann text, binary oder json sein.

  • json: Die Daten können ein beliebiger Typ sein, der von JSON unterstützt wird, und werden in ihrem jeweiligen Zustand veröffentlicht. Der Standardwert ist json.
  • text: Die Daten liegen im Zeichenfolgenformat vor, und die Zeichenfolgendaten werden veröffentlicht.
  • binary: Die Daten liegen im base64-Format vor, und die binären Daten werden veröffentlicht.

Fall 1: Ereignis mit Textdaten versenden:

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

Der Upstreamereignishandler empfängt Daten ähnlich wie:

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

Content-Type für die CloudEvents-HTTP-Anforderung ist text/plain, wenn dataType den Wert text hat.

Fall 2: Ereignis mit JSON-Daten versenden:

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

Der Upstreamereignishandler empfängt Daten ähnlich wie:

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

Content-Type für die CloudEvents-HTTP-Anforderung ist application/json, wenn dataType den Wert json hat.

Fall 3: Ereignis mit Binärdaten versenden:

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

Der Upstreamereignishandler empfängt Daten ähnlich wie:

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

Content-Type für die CloudEvents-HTTP-Anforderung ist application/octet-stream, wenn dataType den Wert binary hat. Der WebSocket-Frame kann entweder das text-Format für Textnachricht-Frames aufweisen oder UTF8-codierte Binärdateien für binary-Nachrichtframes enthalten.

Der Web PubSub-Dienst lehnt den Client ab, wenn die Nachricht nicht dem beschriebenen Format entspricht.

Ping

Format:

{
    "type": "ping",
}

Der Client kann eine ping-Nachricht an den Dienst senden, um den Web PubSub-Dienst zu aktivieren, damit die Aktivität des Clients erkannt werden kann.

Antworten

Nachrichtentypen, die vom Client empfangen werden, können wie folgt sein:

  • ack - Die Antwort auf eine Anforderung, die eine ackId.
  • message – Nachrichten von der Gruppe oder dem Server.
  • system – Nachrichten aus dem Web PubSub-Dienst.
  • Pong - Die Antwort auf eine ping Nachricht.
  • streamAck – Die Antwort, die akzeptierte Stromdaten bestätigt und die nächste erwartete Stream-Sequenz-ID meldet.
  • streamNack – Die Antwort auf einen wiederholbaren Streamfehler.
  • streamClosed – Die Antwort auf die Schließung des Terminals auf der Publisher-Seite des Streams.

Ack-Antwort

Wenn die Clientanforderung enthält ackId, gibt der Dienst eine Ack-Antwort für die Anforderung zurück. Der Client sollte den Ack-Mechanismus behandeln, indem er auf die Ack-Antwort mit einem asyncawait Vorgang wartet und einen Timeoutvorgang verwendet, wenn die Ack-Antwort in einem bestimmten Zeitraum nicht empfangen wird.

Format:

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

Die Clientimplementierung SOLLTE immer überprüfen, ob das success ist true oder false zuerst, und dann nur den Fehler lesen, wenn success das ist false.

Reaktion auf die Nachricht

Clients können Nachrichten entweder von einer Gruppe empfangen, in die der Client eingebunden ist, oder vom Server. Dieser verwendet eine Serververwaltungsrolle und sendet Nachrichten an bestimmte Clients oder Benutzer.

  1. Wenn die Nachricht aus einer Gruppe stammt

    {
        "type": "message",
        "from": "group",
        "group": "<group_name>",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
        "fromUserId": "abc"
    }
    
  2. Wenn die Nachricht vom Server stammt,

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

Fall 1: Senden der Daten Hallo Welt an die Verbindung über die REST-API mit Content-Type=text/plain

  • Ein einfacher WebSocket-Client empfängt einen WebSocket-Textframe mit Daten: Hallo Welt;

  • Ein PubSub WebSocket-Client empfängt:

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

Fall 2: Senden der Daten { "Hello" : "World"} an die Verbindung über die REST-API mit Content-Type=application/json

  • Ein einfacher WebSocket-Client empfängt einen Text-WebSocket-Frame mit Zeichenfolgendaten: { "Hello" : "World"}.

  • Ein PubSub WebSocket-Client empfängt:

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

Wenn die REST-API eine Zeichenfolge Hallo Welt mit application/json dem Inhaltstyp sendet, empfängt der einfache WebSocket-Client eine JSON-Zeichenfolge, die mit doppelten Anführungszeichen ("Hallo Welt") umschlossen wird".

Fall 3: Senden der von Binärdaten an die Verbindung über die REST-API mit Content-Type=application/octet-stream

  • Ein einfacher WebSocket-Client empfängt einen binären WebSocket-Frame mit den Binärdaten.

  • Ein PubSub WebSocket-Client empfängt:

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

Antwort auf Streaming-Nachrichten

Wenn eine Nachricht zu einem Strom gehört, enthält die Gruppennachricht eine Eigenschaft stream .

{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType": "json|text|binary",
    "data": {},
    "fromUserId": "abc",
    "stream": {
        "streamId": "<stream_id>",
        "streamSequenceId": 1,
        "endOfStream": true,
        "error": {
            "name": "IdleTimeout|InternalServerError|Forbidden|Cancelled|UserError",
            "message": "<error_detail>",
            "userErrorCode": "<application_error_code>"
        }
    }
}
  • stream.streamId ist die logische Stromidentifikator.
  • stream.streamSequenceId ist die Sequenznummer der Nachricht im Strom.
  • stream.endOfStream ist optional. Wenn auf truegesetzt ist, ist die Nachricht die Endnachricht des Stroms.
  • stream.error optional ist und nur dann vorhanden, wenn der Stream mit einem Fehler endet. userErrorCode nur für UserErrorvorhanden ist.

Stream-Ack-Reaktion

Der Dienst sendet eine streamAck Antwort, um akzeptierte Stromdaten zu bestätigen und die nächste erwartete Stream-Sequenz-ID zu melden.

Format:

{
    "type": "streamAck",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2
}

Stream-Nack-Reaktion

Der Dienst sendet eine streamNack Antwort auf einen wiederholbaren Stromfehler.

Format:

{
    "type": "streamNack",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2,
    "name": "InvalidSequenceId|TransientError",
    "message": "<error_detail>"
}

Stream geschlossene Antwort

Der Dienst sendet eine streamClosed Antwort, wenn der publisher-seitige Stream geschlossen wird.

Format:

{
    "type": "streamClosed",
    "streamId": "<stream_id>",
    "error": {
        "name": "StreamNotFound|Forbidden|BadRequest|InternalServerError|IdleTimeout",
        "message": "<error_detail>"
    }
}

Die Immobilie error wird weggelassen, wenn der Bach normal geschlossen wird.

Systemantwort

Der Web PubSub-Dienst sendet systembezogene Nachrichten an Clients.

Pong-Antwort

Der Web PubSub-Dienst sendet eine pong-Nachricht an den Client, wenn er eine ping-Nachricht vom Client empfängt.

Format:

{
    "type": "pong",
}

Verbunden

Die An den Client gesendete Nachricht, wenn der Client erfolgreich eine Verbindung herstellt:

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

Getrennt

Die an den Client gesendete Nachricht, wenn der Server die Verbindung schließt, oder wenn der Dienst den Client ablehnt.

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

Nächste Schritte

Erstellen Sie mithilfe dieser Ressourcen Ihre eigene Anwendung: