Mise à jour du client Pusher pour Delphi

· Fonctionnalités

Le composant TsgcWS_API_Pusher a été mis à jour pour s'aligner sur la dernière spécification du protocole Pusher Channels. Cette version introduit la prise en charge des canaux privés chiffrés, quatre nouveaux événements de canaux présence et cache, deux nouveaux endpoints REST, des paramètres de requête améliorés pour les endpoints existants et plusieurs corrections de bugs. Tous les changements sont rétrocompatibles — le code existant continue de fonctionner sans modification.

Table des matières

  1. Prise en charge des canaux privés chiffrés
  2. Nouveaux événements WebSocket
  3. Nouvelles méthodes API REST
  4. Méthodes API REST mises à jour
  5. Corrections de bugs
  6. Résumé

1. Prise en charge des canaux privés chiffrés

Pusher Channels prend en charge les canaux privés chiffrés qui fournissent un chiffrement de bout en bout des données d'événement via NaCl Secretbox (XSalsa20-Poly1305). Les serveurs Pusher ne voient jamais le texte en clair — seuls les clients communicants peuvent déchiffrer les messages. Deux nouveaux types de canaux ont été ajoutés à l'énumération TsgcWSPusherChannels :

Valeur d'énumération Préfixe du canal Description
pscPrivateEncryptedChannel private-encrypted- Canal privé chiffré de bout en bout. Les charges utiles sont chiffrées avec un secret partagé par canal.
pscPrivateEncryptedCacheChannel private-encrypted-cache- Identique à ci-dessus, avec le comportement de cache channel — le dernier événement est délivré aux nouveaux abonnés.

La classe TsgcWSPusherResponseAuthentication inclut désormais une propriété SharedSecret. Lors de l'abonnement à un canal private-encrypted-, ton endpoint d'autorisation doit renvoyer le secret partagé par canal encodé en base64. Définis cette valeur dans le gestionnaire d'événement OnPusherAuthentication :

procedure TForm1.sgcPusherAuthentication(Sender: TObject;
  AuthRequest: TsgcWSPusherRequestAuthentication;
  AuthResponse: TsgcWSPusherResponseAuthentication);
begin
  // Pour les canaux privés chiffrés, définis le secret partagé
  // renvoyé par ton serveur d'autorisation
  AuthResponse.Secret := 'your-app-secret';
  AuthResponse.SharedSecret := 'base64-encoded-per-channel-key';
end;

S'abonner à un canal chiffré

// S'abonner à un canal privé chiffré
sgcPusher.Subscribe('my-secret-channel', pscPrivateEncryptedChannel);
// S'abonner à un cache channel privé chiffré
sgcPusher.Subscribe('my-secret-cache', pscPrivateEncryptedCacheChannel);

Publier sur un canal chiffré

// Les événements client fonctionnent sur les canaux privés chiffrés comme sur les canaux privés
sgcPusher.Publish('my-event', 'my-secret-channel',
  pscPrivateEncryptedChannel, '{"message":"Hello encrypted!"}');

2. Nouveaux événements WebSocket

Quatre nouveaux événements ont été ajoutés pour gérer les messages internes du protocole Pusher qui n'étaient pas gérés auparavant. Ces événements sont déclenchés automatiquement lorsque les messages pusher_internal: correspondants arrivent via la connexion WebSocket.

Propriété d'événement Message du protocole Description
OnPusherMemberAdded pusher_internal:member_added Déclenché quand un nouvel utilisateur rejoint un canal présence. Fournit le nom du canal, l'ID utilisateur et les infos utilisateur.
OnPusherMemberRemoved pusher_internal:member_removed Déclenché quand un utilisateur quitte un canal présence. Fournit le nom du canal, l'ID utilisateur et les infos utilisateur.
OnPusherSubscriptionCount pusher_internal:subscription_count Déclenché quand le nombre d'abonnements à un canal change. Doit être activé dans le tableau de bord Pusher.
OnPusherCacheMiss pusher_internal:cache_miss Déclenché lors de l'abonnement à un cache channel sans événement en cache disponible.

OnPusherMemberAdded / OnPusherMemberRemoved

Ces événements utilisent le nouveau type de callback TsgcWSPusherMemberEvent, qui fournit le nom du canal, l'ID utilisateur et les infos utilisateur en paramètres séparés :

TsgcWSPusherMemberEvent = procedure(Sender: TObject;
  Channel, UserId, UserInfo: String) of object;
procedure TForm1.sgcPusherMemberAdded(Sender: TObject;
  Channel, UserId, UserInfo: String);
begin
  Memo1.Lines.Add('User joined: ' + UserId + ' on ' + Channel);
  if UserInfo  '' then
    Memo1.Lines.Add('  Info: ' + UserInfo);
end;
procedure TForm1.sgcPusherMemberRemoved(Sender: TObject;
  Channel, UserId, UserInfo: String);
begin
  Memo1.Lines.Add('User left: ' + UserId + ' from ' + Channel);
end;

OnPusherSubscriptionCount

Utilise le nouveau type de callback TsgcWSPusherSubscriptionCountEvent. Cet événement nécessite que la fonctionnalité Subscription Count soit activée dans les paramètres de ton tableau de bord Pusher.

TsgcWSPusherSubscriptionCountEvent = procedure(Sender: TObject;
  Channel: String; SubscriptionCount: Integer) of object;
procedure TForm1.sgcPusherSubscriptionCount(Sender: TObject;
  Channel: String; SubscriptionCount: Integer);
begin
  Memo1.Lines.Add(Channel + ' now has ' + IntToStr(SubscriptionCount) +
    ' subscribers');
end;

OnPusherCacheMiss

Utilise le nouveau type de callback TsgcWSPusherCacheMissEvent. Cet événement est déclenché lorsque tu t'abonnes à un cache channel (cache-, private-cache-, private-encrypted-cache- ou presence-cache-) et qu'aucun événement en cache n'est disponible.

TsgcWSPusherCacheMissEvent = procedure(Sender: TObject;
  Channel: String) of object;
procedure TForm1.sgcPusherCacheMiss(Sender: TObject; Channel: String);
begin
  Memo1.Lines.Add('No cached event for channel: ' + Channel);
end;

3. Nouvelles méthodes API REST

Deux nouvelles méthodes API REST côté serveur ont été ajoutées au composant TsgcWS_API_Pusher, couvrant l'endpoint batch events et la résiliation de connexion utilisateur.

Méthode Endpoint Pusher Description
TriggerBatchEvents POST /apps/{app_id}/batch_events Déclenche jusqu'à 10 événements dans une seule requête HTTP. Chaque événement peut cibler un canal différent.
TerminateUserConnections POST /apps/{app_id}/users/{user_id}/terminate_connections Termine toutes les connexions WebSocket d'un utilisateur authentifié spécifique.

TriggerBatchEvents

function TriggerBatchEvents(const aBatch: String): String;

Le paramètre aBatch est une chaîne JSON contenant un tableau batch d'objets événement. Chaque objet doit inclure channel, name et data. Maximum 10 événements par batch.

var
  vBatch, vResult: string;
begin
  vBatch :=
    '{"batch": [' +
    '  {"channel": "my-channel-1", "name": "my-event", "data": "{\"msg\":\"hello\"}"}' + ',' +
    '  {"channel": "my-channel-2", "name": "my-event", "data": "{\"msg\":\"world\"}"}' +
    ']}';
  vResult := sgcPusher.TriggerBatchEvents(vBatch);
  Memo1.Lines.Add(vResult);
end;

TerminateUserConnections

function TerminateUserConnections(const aUserId: String): String;

Termine de force toutes les connexions WebSocket actives d'un utilisateur donné. Utile pour déconnecter un utilisateur sur tous ses appareils ou révoquer l'accès après un changement d'autorisation. Nécessite que la User Authentication Pusher soit configurée.

var
  vResult: string;
begin
  // Déconnecter l'utilisateur « user-123 » de toutes les sessions
  vResult := sgcPusher.TerminateUserConnections('user-123');
  Memo1.Lines.Add(vResult);
end;

4. Méthodes API REST mises à jour

Trois méthodes API REST existantes ont été enrichies de paramètres optionnels supplémentaires. Comme les nouveaux paramètres ont tous des valeurs par défaut, le code existant est entièrement rétrocompatible.

TriggerEvent

Previous Signature

function TriggerEvent(const aEventName, aChannel, aData: String): String;

New Signature

function TriggerEvent(const aEventName, aChannel, aData: String;
  const aSocketId: String = '';
  const aInfo: String = ''): String;
Paramètre Description
aSocketId Exclut ce socket ID de la réception de l'événement. Utile pour empêcher l'expéditeur de recevoir son propre broadcast.
aInfo Liste d'attributs à renvoyer, séparés par des virgules. Valeurs valides : subscription_count, user_count.
var
  vResult: string;
begin
  // Déclencher un événement, exclure l'expéditeur et demander le nombre d'abonnements
  vResult := sgcPusher.TriggerEvent('my-event', 'my-channel',
    '{"msg":"hello"}', sgcPusher.FSocket_id, 'subscription_count');
  Memo1.Lines.Add(vResult);
  // Response: {"channels":{"my-channel":{"subscription_count":5}}}
end;

GetChannels

Previous Signature

function GetChannels: String;

New Signature

function GetChannels(
  const aFilterByPrefix: String = '';
  const aInfo: String = ''): String;
Parameter Description
aFilterByPrefix Filtre les canaux renvoyés par préfixe de nom. Exemple : presence- ne renvoie que les canaux présence.
aInfo Attributs séparés par des virgules. Valeurs valides : user_count (présence uniquement), subscription_count.
var
  vResult: string;
begin
  // Lister tous les canaux présence avec le nombre d'utilisateurs
  vResult := sgcPusher.GetChannels('presence-', 'user_count');
  Memo1.Lines.Add(vResult);
  // Response: {"channels":{"presence-room":{"user_count":3}}}
  // Lister tous les canaux (pas de filtre) - appel rétrocompatible
  vResult := sgcPusher.GetChannels;
  Memo1.Lines.Add(vResult);
end;

GetChannel

Previous Signature

function GetChannel(const aChannel: String): String;

New Signature

function GetChannel(const aChannel: String;
  const aInfo: String = ''): String;
Parameter Description
aInfo Attributs séparés par des virgules. Valeurs valides : subscription_count, user_count, cache.
var
  vResult: string;
begin
  // Obtenir les infos du canal avec subscription_count et user_count
  vResult := sgcPusher.GetChannel('presence-room',
    'subscription_count,user_count');
  Memo1.Lines.Add(vResult);
  // Response: {"occupied":true,"subscription_count":5,"user_count":3}
  // Obtenir les infos de base du canal - appel rétrocompatible
  vResult := sgcPusher.GetChannel('my-channel');
  Memo1.Lines.Add(vResult);
end;

5. Corrections de bugs

Plusieurs bugs ont été identifiés et corrigés dans cette version :

Bug Impact Correctif
Faute de frappe dans DoReadEvent : 'puserh:ping' Critique Les pings serveur n'étaient jamais reconnus, ce qui faisait manquer au client les requêtes de heartbeat. Cela pouvait conduire à ce que le serveur déconnecte le client pour inactivité. Corrigé en 'pusher:ping'.
Accès null dans DoSendPong Élevé L'accès à JSON.Node['data'].Value sans vérification null pouvait provoquer une violation d'accès si le message ping n'avait pas de champ data. Vérification null ajoutée ; valeur par défaut {} en l'absence de données.
Préfixe en dur dans GetUsers Élevé La méthode ajoutait systématiquement presence- au nom du canal, doublant le préfixe si l'utilisateur passait déjà le nom complet (par exemple presence-presence-room). Préfixe en dur supprimé. Les utilisateurs doivent désormais passer le nom complet du canal, préfixe presence- inclus.
Double point-virgule dans GetUsers Faible Un double point-virgule ;; traînait à la fin de la méthode. Suppression du point-virgule en trop.

Changement cassant dans GetUsers : la méthode GetUsers ne préfixe plus presence- automatiquement. Si ton code passe juste le nom du canal sans préfixe (par exemple GetUsers('my-room')), tu dois le mettre à jour pour inclure le nom complet : GetUsers('presence-my-room').


6. Résumé

Catégorie Nombre Détails
Nouveaux types de canaux 2 pscPrivateEncryptedChannel, pscPrivateEncryptedCacheChannel
Nouveaux événements WebSocket 4 OnPusherMemberAdded, OnPusherMemberRemoved, OnPusherSubscriptionCount, OnPusherCacheMiss
Nouvelles méthodes REST 2 TriggerBatchEvents, TerminateUserConnections
Méthodes REST mises à jour 3 TriggerEvent (+socket_id, +info), GetChannels (+filter, +info), GetChannel (+info)
Nouvelles propriétés 1 SharedSecret on TsgcWSPusherResponseAuthentication
Corrections de bugs 4 Typo de ping, accès null de pong, préfixe GetUsers, double point-virgule

Tous les changements sont rétrocompatibles. Les nouveaux paramètres de méthode utilisent des valeurs par défaut et les nouvelles propriétés d'événement sont optionnelles. Le seul changement de comportement concerne GetUsers, qui ne préfixe plus presence- automatiquement.