Le sous-protocole protobuf WebSocket pris en charge par Azure Web PubSub
Ce document décrit le sous-protocole protobuf.webpubsub.azure.v1
.
Lorsqu’un client utilise ce sous-protocole, les trames de données entrantes et sortantes sont supposées être des charges utiles de mémoires tampon de protocole (protobuf).
Vue d’ensemble
Le sous-protocole protobuf.webpubsub.azure.v1
permet aux clients de publier/s’abonner (PubSub) directement au lieu d’effectuer un aller-retour au serveur en amont. La connexion WebSocket avec le sous-protocole protobuf.webpubsub.azure.v1
est appelée un client WebSocket PubSub.
Par exemple, dans JavaScript, vous pouvez créer un client WebSocket PubSub avec le sous-protocole protobuf à l’aide des éléments suivants :
// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');
Pour un client WebSocket simple, le serveur a le rôle nécessaire de gestion des événements des clients. Une connexion WebSocket simple déclenche toujours un événement message
lors de l’envoi de messages, et il s’appuie toujours sur le côté serveur pour traiter les messages et effectuer d’autres opérations. Avec l’aide du sous-protocole protobuf.webpubsub.azure.v1
, un client autorisé peut rejoindre un groupe avec des requêtes d’adhésion et publier des messages directement dans un groupe avec des requêtes de publication. Le client peut également router des messages vers différents gestionnaires d’événements en amont avec des requêtes d’événement pour personnaliser l’événement auquel le message appartient.
Remarque
Actuellement, le service Web PubSub ne prend en charge que proto3.
autorisations
Un client PubSub WebSocket peut publier sur d’autres clients seulement s’il est autorisé. Les roles
attribués au client déterminent les autorisations accordées au client :
Rôle | Autorisation |
---|---|
Non spécifié(e) | Le client peut envoyer des requêtes d’événements. |
webpubsub.joinLeaveGroup |
Le client peut rejoindre/quitter n’importe quel groupe. |
webpubsub.sendToGroup |
Le client peut publier des messages dans n’importe quel groupe. |
webpubsub.joinLeaveGroup.<group> |
Le client peut rejoindre/quitter le groupe <group> . |
webpubsub.sendToGroup.<group> |
Le client peut publier des messages sur le groupe <group> . |
Le serveur peut accorder ou révoquer les autorisations d’un client de manière dynamique en utilisant des API REST ou des SDK de serveur.
Demandes
Tous les messages de requête adhèrent au format protobuf suivant :
syntax = "proto3";
import "google/protobuf/any.proto";
message UpstreamMessage {
oneof message {
SendToGroupMessage send_to_group_message = 1;
EventMessage event_message = 5;
JoinGroupMessage join_group_message = 6;
LeaveGroupMessage leave_group_message = 7;
}
message SendToGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
MessageData data = 3;
}
message EventMessage {
string event = 1;
MessageData data = 2;
optional uint64 ack_id = 3;
}
message JoinGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
}
message LeaveGroupMessage {
string group = 1;
optional uint64 ack_id = 2;
}
}
message MessageData {
oneof data {
string text_data = 1;
bytes binary_data = 2;
google.protobuf.Any protobuf_data = 3;
}
}
Rejoindre des groupes
Format :
Définissez join_group_message.group
sur le nom du groupe.
ackId
est l’identité de chaque demande et doit être unique. Le service envoie un message de réponse Ack pour notifier le résultat du processus de la demande. Pour plus d’informations, consultez AckId et réponse Ack.
Quitter des groupes
Format :
Définissez leave_group_message.group
sur le nom du groupe.
ackId
est l’identité de chaque demande et doit être unique. Le service envoie un message de réponse Ack pour notifier le résultat du processus de la demande. Pour plus d’informations, consultez AckId et réponse Ack.
Publier des messages
Format :
ackId
: identité unique de chaque demande. Le service envoie un message de réponse d’accusé de réception (ack) pour notifier le résultat du processus de la demande. Pour plus d’informations, consultez AckId et réponse Ack.dataType
: le format de données, qui peut êtreprotobuf
,text
oubinary
selon lesdata
dansMessageData
. Les clients destinataires peuvent utiliserdataType
pour traiter correctement le contenu.protobuf
: si vous définissezsend_to_group_message.data.protobuf_data
, la valeur implicite dedataType
estprotobuf
.protobuf_data
peut être Tout type de message. Tous les autres clients reçoivent un binaire encodé en protobuf, qui peut être désérialisé par le kit de développement logiciel (SDK) protobuf. Les clients qui ne prennent en charge que le contenu texte (par exemple,json.webpubsub.azure.v1
) reçoivent un binaire encodé en Base64.text
: si vous définissezsend_to_group_message.data.text_data
, la valeur implicite dedataType
esttext
.text_data
doit être une chaîne. Tous les clients avec d’autres protocoles reçoivent une chaîne encodée en UTF-8.binary
: si vous définissezsend_to_group_message.data.binary_data
, la valeur implicite dedataType
estbinary
.binary_data
doit être un tableau d’octets. Tous les clients avec d’autres protocoles reçoivent un binaire brut sans encodage protobuf. Les clients qui ne prennent en charge que le contenu texte (par exemple,json.webpubsub.azure.v1
) reçoivent un binaire encodé en Base64.
Cas 1 : publier des données texte
Définissez send_to_group_message.group
sur group
, et send_to_group_message.data.text_data
sur "text data"
.
Le client de sous-protocole protobuf du groupe
group
reçoit la trame binaire et peut utiliser DownstreamMessage pour la désérialiser.Les clients du sous-protocole JSON dans
group
reçoivent :{ "type": "message", "from": "group", "group": "group", "dataType" : "text", "data" : "text data" }
Les clients WebSocket simples dans
group
reçoivent la chaînetext data
.
Cas 2 : publier des données protobuf
Supposons que vous avez un message de client :
message MyMessage {
int32 value = 1;
}
Définissez send_to_group_message.group
sur group
, et send_to_group_message.data.protobuf_data
sur Any.pack(MyMessage)
avec value = 1
.
Le client de sous-protocole protobuf dans
group
reçoit la trame binaire et peut utiliser DownstreamMessage pour la désérialiser.Le client de sous-protocole dans
group
reçoit :{ "type": "message", "from": "group", "group": "G", "dataType" : "protobuf", "data" : "Ci90eXBlLmdvb2dsZWFwaXMuY29tL2F6dXJlLndlYnB1YnN1Yi5UZXN0TWVzc2FnZRICCAE=" // Base64-encoded bytes }
Remarque
Les données correspondent à un binaire protobuf désérialisable, encodé en Base64.
Vous pouvez utiliser la définition protobuf suivante et la désérialiser avec Any.unpack()
:
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Les clients WebSocket simples dans
group
reçoivent la trame binaire :# Show in hexadecimal 0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
Cas 3 : publier des données binaires
Définissez send_to_group_message.group
sur group
, et send_to_group_message.data.binary_data
sur [1, 2, 3]
.
Le client de sous-protocole protobuf du groupe
group
reçoit la trame binaire et peut utiliser DownstreamMessage pour la désérialiser.Le client de sous-protocole JSON du groupe
group
reçoit :{ "type": "message", "from": "group", "group": "group", "dataType" : "binary", "data" : "AQID", // Base64-encoded [1,2,3] }
Étant donné que le client de sous-protocole JSON ne prend en charge que la messagerie texte, le binaire est toujours encodé en Base64.
Les clients WebSocket simples dans
group
reçoivent les données binaires dans la trame binaire :# Show in hexadecimal 01 02 03
Envoyer des événements personnalisés
Il existe un dataType
implicite, qui peut être protobuf
, text
ou binary
, en fonction du dataType
que vous définissez. Les clients récepteurs peuvent utiliser dataType
pour traiter correctement le contenu.
protobuf
: si vous définissezevent_message.data.protobuf_data
, la valeur implicite dedataType
estprotobuf
. La valeur deprotobuf_data
peut être n’importe quel type protobuf pris en charge. Le gestionnaire d’événements reçoit le binaire encodé en protobuf, qui peut être désérialisé par n’importe quel kit de développement logiciel (SDK) protobuf.text
: si vous définissezevent_message.data.text_data
, la valeur implicite dedataType
esttext
. La valeur detext_data
doit être une chaîne. Le gestionnaire d’événements reçoit une chaîne encodée en UTF-8.binary
: si vous définissezevent_message.data.binary_data
, la valeur implicite dedataType
estbinary
. La valeur debinary_data
doit être un tableau d’octets. Le gestionnaire d’événements reçoit la trame binaire brute.
Cas 1 : envoyer un événement avec des données texte
Affectez la valeur event_message.data.text_data
à "text data"
.
Le gestionnaire d’événements en amont reçoit une demande semblable à la suivante :
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
Le Content-Type
de la requête HTTP CloudEvents est text/plain
, où dataType
=text
.
Cas 2 : envoyer un événement avec des données protobuf
Supposons que vous avez reçu le message de client suivant :
message MyMessage {
int32 value = 1;
}
Définissez event_message.data.protobuf_data
sur any.pack(MyMessage)
avec value = 1
Le gestionnaire d’événements en amont reçoit une demande semblable à la suivante :
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>
// Just show in hexadecimal; read it as binary
0A 2F 74 79 70 65 2E 67 6F 6F 67 6C 65 61 70 69 73 2E 63 6F 6D 2F 61 7A 75 72 65 2E 77 65 62 70 75 62 73 75 62 2E 54 65 73 74 4D 65 73 73 61 67 65 12 02 08 01
Le Content-Type
de la requête HTTP CloudEvents est application/x-protobuf
, où dataType
=protobuf
.
Les données correspondent à un binaire protobuf valide. Vous pouvez utiliser les paramètres proto
et any.unpack()
suivants pour le désérialiser :
syntax = "proto3";
message MyMessage {
int32 value = 1;
}
Cas 3 : envoyer un événement avec des données binaires
Affectez la valeur send_to_group_message.binary_data
à [1, 2, 3]
.
Le gestionnaire d’événements en amont reçoit une demande semblable à la suivante :
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>
// Just show in hexadecimal; you need to read it as binary
01 02 03
Pour dataType
=binary
, la valeur de Content-Type
pour la requête HTTP CloudEvents est application/octet-stream
. La trame WebSocket peut être au format text
pour les trames de message texte ou de binaires encodés en UTF-8 pour les trames de message binary
.
Le service refuse le client si le message ne correspond pas au format prescrit.
Réponses
Tous les messages de réponse adhèrent au format protobuf suivant :
message DownstreamMessage {
oneof message {
AckMessage ack_message = 1;
DataMessage data_message = 2;
SystemMessage system_message = 3;
}
message AckMessage {
uint64 ack_id = 1;
bool success = 2;
optional ErrorMessage error = 3;
message ErrorMessage {
string name = 1;
string message = 2;
}
}
message DataMessage {
string from = 1;
optional string group = 2;
MessageData data = 3;
}
message SystemMessage {
oneof message {
ConnectedMessage connected_message = 1;
DisconnectedMessage disconnected_message = 2;
}
message ConnectedMessage {
string connection_id = 1;
string user_id = 2;
}
message DisconnectedMessage {
string reason = 2;
}
}
}
Les messages reçus par le client peuvent être de trois types : ack
, message
ou system
.
Réponse ACK
Si la requête contient ackId
, le service renvoie une réponse ACK pour cette requête. L’implémentation du client doit gérer ce mécanisme d’acquittement (ack), y compris :
- Attendre la réponse ACK pour une opération
async
await
. - Vérification du délai d’attente lorsque la réponse ACK n’est pas reçue au cours d’une certaine période.
L’implémentation du client doit toujours d’abord vérifier si l’état success
est true
ou false
. Lorsque l’état success
est false
, le client peut lire les détails de l’erreur dans la propriété error
.
Réponse de message
Les clients peuvent recevoir des messages publiés à partir d’un groupe auquel le client s’est joint. Autrement, ils peuvent recevoir des messages du rôle gestion de serveur lorsque le serveur envoie des messages à un client spécifique ou à un utilisateur spécifique.
Vous obtiendrez toujours un message DownstreamMessage.DataMessage
dans les scénarios suivants :
- Lorsque le message provient d’un groupe, la valeur de
from
estgroup
. Lorsque le message provient du serveur, la valeur defrom
estserver
. - Lorsque le message provient d’un groupe, la valeur de
group
est le nom du groupe.
Le paramètre dataType
de l’expéditeur entraînera l’envoi de l’un des messages suivants :
- Si la valeur de
dataType
esttext
, utilisezmessage_response_message.data.text_data
. - Si la valeur de
dataType
estbinary
, utilisezmessage_response_message.data.binary_data
. - Si la valeur de
dataType
estprotobuf
, utilisezmessage_response_message.data.protobuf_data
. - Si la valeur de
dataType
estjson
, utilisezmessage_response_message.data.text_data
, et le contenu est une chaîne JSON sérialisée.
Réponse du système
Le service Web PubSub peut également envoyer au client des réponses liées au système.
Connecté
Lorsque le client se connecte au service, vous recevez un message DownstreamMessage.SystemMessage.ConnectedMessage
.
Déconnecté
Lorsque le serveur clôt la connexion ou que le service refuse le client, vous recevez un message DownstreamMessage.SystemMessage.DisconnectedMessage
.
Étapes suivantes
Utilisez ces ressources pour commencer à créer votre propre application :