Aggiornamento client Pusher per Delphi

· Funzionalità

Il componente TsgcWS_API_Pusher è stato aggiornato per allinearsi all'ultima Pusher Channels protocol specification. Questa release introduce il supporto per canali private-encrypted, quattro nuovi eventi per canali presence e cache, due nuovi endpoint REST API, parametri di query migliorati per gli endpoint esistenti e diverse correzioni di bug. Tutte le modifiche sono retrocompatibili: il codice esistente continua a funzionare senza modifiche.

Indice

  1. Supporto canali private-encrypted
  2. Nuovi eventi WebSocket
  3. Nuovi metodi REST API
  4. Metodi REST API aggiornati
  5. Bug fix
  6. Riepilogo

1. Supporto canali private-encrypted

Pusher Channels supporta i canali private-encrypted che forniscono la cifratura end-to-end dei dati degli eventi usando NaCl Secretbox (XSalsa20-Poly1305). I server Pusher non vedono mai il testo in chiaro: solo i client in comunicazione possono decifrare i messaggi. Due nuovi tipi di canale sono stati aggiunti all'enumerazione TsgcWSPusherChannels:

Valore enum Prefisso del canale Descrizione
pscPrivateEncryptedChannel private-encrypted- Canale privato cifrato end-to-end. I payload dei dati sono cifrati con un segreto condiviso per canale.
pscPrivateEncryptedCacheChannel private-encrypted-cache- Come sopra, più il comportamento di cache channel: l'ultimo evento viene consegnato ai nuovi sottoscrittori.

La classe TsgcWSPusherResponseAuthentication ora include la proprietà SharedSecret. Quando ti sottoscrivi a un canale private-encrypted-, il tuo endpoint di autorizzazione deve restituire il segreto condiviso per canale codificato in base64. Imposta questo valore nel gestore di eventi OnPusherAuthentication:

procedure TForm1.sgcPusherAuthentication(Sender: TObject;
  AuthRequest: TsgcWSPusherRequestAuthentication;
  AuthResponse: TsgcWSPusherResponseAuthentication);
begin
  // For private-encrypted channels, set the shared secret
  // returned by your authorization server
  AuthResponse.Secret := 'your-app-secret';
  AuthResponse.SharedSecret := 'base64-encoded-per-channel-key';
end;

Sottoscrizione a un canale cifrato

// Subscribe to a private-encrypted channel
sgcPusher.Subscribe('my-secret-channel', pscPrivateEncryptedChannel);
// Subscribe to a private-encrypted cache channel
sgcPusher.Subscribe('my-secret-cache', pscPrivateEncryptedCacheChannel);

Pubblicazione su un canale cifrato

// Client events work on private-encrypted channels just like private channels
sgcPusher.Publish('my-event', 'my-secret-channel',
  pscPrivateEncryptedChannel, '{"message":"Hello encrypted!"}');

2. Nuovi eventi WebSocket

Sono stati aggiunti quattro nuovi eventi per gestire i messaggi di protocollo interno di Pusher che prima non erano gestiti. Questi eventi vengono attivati automaticamente quando i corrispondenti messaggi pusher_internal: arrivano sulla connessione WebSocket.

Proprietà evento Messaggio di protocollo Descrizione
OnPusherMemberAdded pusher_internal:member_added Attivato quando un nuovo utente entra in un canale presence. Fornisce il nome del canale, l'ID utente e le info utente.
OnPusherMemberRemoved pusher_internal:member_removed Attivato quando un utente esce da un canale presence. Fornisce il nome del canale, l'ID utente e le info utente.
OnPusherSubscriptionCount pusher_internal:subscription_count Attivato quando cambia il conteggio delle sottoscrizioni di un canale. Deve essere abilitato nella dashboard Pusher.
OnPusherCacheMiss pusher_internal:cache_miss Attivato quando ci si sottoscrive a un cache channel che non ha alcun evento in cache disponibile.

OnPusherMemberAdded / OnPusherMemberRemoved

Questi eventi usano il nuovo tipo di callback TsgcWSPusherMemberEvent, che fornisce il nome del canale, l'ID utente e le info utente come parametri separati:

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

Usa il nuovo tipo di callback TsgcWSPusherSubscriptionCountEvent. Questo evento richiede che la funzionalità Subscription Count sia abilitata nelle impostazioni della dashboard 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

Usa il nuovo tipo di callback TsgcWSPusherCacheMissEvent. Questo evento viene attivato quando ti sottoscrivi a un cache channel (cache-, private-cache-, private-encrypted-cache- o presence-cache-) e non è disponibile alcun evento in cache.

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. Nuovi metodi REST API

Sono stati aggiunti due nuovi metodi REST API server-side al componente TsgcWS_API_Pusher, che coprono l'endpoint batch events e la terminazione delle connessioni utente.

Metodo Endpoint Pusher Descrizione
TriggerBatchEvents POST /apps/{app_id}/batch_events Attiva fino a 10 eventi in una singola richiesta HTTP. Ogni evento può puntare a un canale diverso.
TerminateUserConnections POST /apps/{app_id}/users/{user_id}/terminate_connections Termina tutte le connessioni WebSocket per un utente autenticato specifico.

TriggerBatchEvents

function TriggerBatchEvents(const aBatch: String): String;

Il parametro aBatch è una stringa JSON che contiene un array batch di oggetti evento. Ogni oggetto deve includere channel, name e data. Massimo 10 eventi per 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;

Termina forzatamente tutte le connessioni WebSocket attive per un dato utente. È utile per disconnettere un utente da tutti i suoi dispositivi o revocare l'accesso dopo una modifica dei permessi. Richiede che User Authentication di Pusher sia configurato.

var
  vResult: string;
begin
  // Disconnect user "user-123" from all sessions
  vResult := sgcPusher.TerminateUserConnections('user-123');
  Memo1.Lines.Add(vResult);
end;

4. Metodi REST API aggiornati

Tre metodi REST API esistenti sono stati arricchiti con parametri opzionali aggiuntivi. Poiché i nuovi parametri hanno tutti valori predefiniti, il codice esistente è pienamente retrocompatibile.

TriggerEvent

Firma precedente

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

Nuova firma

function TriggerEvent(const aEventName, aChannel, aData: String;
  const aSocketId: String = '';
  const aInfo: String = ''): String;
Parametro Descrizione
aSocketId Escludi questo socket ID dalla ricezione dell'evento. Utile per evitare che il mittente riceva il proprio broadcast.
aInfo Lista di attributi separati da virgola da restituire. Valori validi: subscription_count, user_count.
var
  vResult: string;
begin
  // Trigger event, exclude the sender, and request subscription count
  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;
Parametro Descrizione
aFilterByPrefix Filtra i canali restituiti per prefisso del nome. Esempio: presence- restituisce solo i canali presence.
aInfo Attributi separati da virgola. Valori validi: user_count (solo presence), subscription_count.
var
  vResult: string;
begin
  // List all presence channels with user counts
  vResult := sgcPusher.GetChannels('presence-', 'user_count');
  Memo1.Lines.Add(vResult);
  // Response: {"channels":{"presence-room":{"user_count":3}}}
  // List all channels (no filter) - backward-compatible call
  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;
Parametro Descrizione
aInfo Attributi separati da virgola. Valori validi: subscription_count, user_count, cache.
var
  vResult: string;
begin
  // Get channel info with subscription count and user count
  vResult := sgcPusher.GetChannel('presence-room',
    'subscription_count,user_count');
  Memo1.Lines.Add(vResult);
  // Response: {"occupied":true,"subscription_count":5,"user_count":3}
  // Get basic channel info - backward-compatible call
  vResult := sgcPusher.GetChannel('my-channel');
  Memo1.Lines.Add(vResult);
end;

5. Bug fix

In questa release sono stati identificati e corretti diversi bug:

Bug Impatto Correzione
Typo in DoReadEvent: 'puserh:ping' Critico i ping del server non venivano mai riconosciuti, facendo perdere al client le richieste di heartbeat. Questo poteva portare il server a disconnettere il client per inattività. Corretto in 'pusher:ping'.
DoSendPong null access Alto accedere a JSON.Node['data'].Value senza controllo null poteva causare una access violation se il messaggio di ping non ha campo data. Aggiunto controllo null; default a {} quando data è assente.
GetUsers hardcoded prefix Alto il metodo anteponeva sempre presence- al nome del canale, raddoppiando il prefisso se l'utente passava già il nome completo del canale (ad es. presence-presence-room). Rimosso il prefisso hardcoded. Gli utenti ora devono passare il nome completo del canale incluso il prefisso presence-.
GetUsers double semicolon Basso alla fine del metodo era presente un doppio punto e virgola ;;. Rimosso il punto e virgola extra.

Breaking change in GetUsers: il metodo GetUsers non antepone più automaticamente presence-. Se il tuo codice passa solo il nome del canale senza il prefisso (ad es. GetUsers('my-room')), devi aggiornarlo per includere il nome completo: GetUsers('presence-my-room').


6. Riepilogo

Categoria Conteggio Dettagli
Nuovi tipi di canale 2 pscPrivateEncryptedChannel, pscPrivateEncryptedCacheChannel
Nuovi eventi WebSocket 4 OnPusherMemberAdded, OnPusherMemberRemoved, OnPusherSubscriptionCount, OnPusherCacheMiss
Nuovi metodi REST 2 TriggerBatchEvents, TerminateUserConnections
Metodi REST aggiornati 3 TriggerEvent (+socket_id, +info), GetChannels (+filter, +info), GetChannel (+info)
Nuove proprietà 1 SharedSecret on TsgcWSPusherResponseAuthentication
Bug fix 4 Refuso nel ping, accesso null nel pong, prefisso di GetUsers, doppio punto e virgola

Tutte le modifiche sono retrocompatibili. I nuovi parametri dei metodi usano valori predefiniti e le nuove proprietà di evento sono opzionali. L'unico cambio di comportamento è in GetUsers, che non antepone più automaticamente il prefisso presence-.