Aktualizacja klienta Pusher dla Delphi

· Funkcje

Komponent TsgcWS_API_Pusher został zaktualizowany, aby był zgodny z najnowszą specyfikacją protokołu Pusher Channels. Ta wersja wprowadza obsługę kanałów private-encrypted, cztery nowe zdarzenia kanałów presence i cache, dwa nowe punkty końcowe REST API, rozszerzone parametry zapytań dla istniejących punktów końcowych i kilka poprawek błędów. Wszystkie zmiany są wstecznie zgodne — istniejący kod działa bez modyfikacji.

Spis treści

  1. Obsługa kanałów private-encrypted
  2. Nowe zdarzenia WebSocket
  3. Nowe metody REST API
  4. Zaktualizowane metody REST API
  5. Poprawki błędów
  6. Podsumowanie

1. Obsługa kanałów private-encrypted

Pusher Channels obsługuje kanały private-encrypted, które zapewniają szyfrowanie end-to-end danych zdarzeń za pomocą NaCl Secretbox (XSalsa20-Poly1305). Serwery Pusher nigdy nie widzą tekstu jawnego — tylko komunikujące się klienty mogą odszyfrować wiadomości. Do wyliczenia TsgcWSPusherChannels dodano dwa nowe typy kanałów:

Wartość wyliczenia Prefiks kanału Opis
pscPrivateEncryptedChannel private-encrypted- Prywatny kanał z szyfrowaniem end-to-end. Dane zdarzeń są szyfrowane wspólnym sekretem per-kanał.
pscPrivateEncryptedCacheChannel private-encrypted-cache- Jak powyżej, plus zachowanie kanału cache — ostatnie zdarzenie jest dostarczane nowym subskrybentom.

Klasa TsgcWSPusherResponseAuthentication zawiera teraz właściwość SharedSecret. Przy subskrypcji kanału private-encrypted- twój punkt końcowy autoryzacji musi zwrócić zakodowany w base64 sekret per-kanał. Ustaw tę wartość w procedurze obsługi zdarzenia 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;

Subskrybowanie kanału szyfrowanego

// 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);

Publikowanie na kanale szyfrowanym

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

2. Nowe zdarzenia WebSocket

Dodano cztery nowe zdarzenia obsługujące wewnętrzne komunikaty protokołu Pusher, które wcześniej nie były obsługiwane. Zdarzenia te są wywoływane automatycznie, gdy do połączenia WebSocket dotrą odpowiednie wiadomości pusher_internal:.

Właściwość zdarzenia Komunikat protokołu Opis
OnPusherMemberAdded pusher_internal:member_added Wywoływane gdy nowy użytkownik dołącza do kanału presence. Dostarcza nazwę kanału, ID użytkownika i informacje o nim.
OnPusherMemberRemoved pusher_internal:member_removed Wywoływane gdy użytkownik opuszcza kanał presence. Dostarcza nazwę kanału, ID użytkownika i informacje o nim.
OnPusherSubscriptionCount pusher_internal:subscription_count Wywoływane gdy zmienia się liczba subskrypcji kanału. Musi być włączone w panelu Pusher.
OnPusherCacheMiss pusher_internal:cache_miss Wywoływane przy subskrybowaniu kanału cache, gdy nie ma dostępnego zbuforowanego zdarzenia.

OnPusherMemberAdded / OnPusherMemberRemoved

Te zdarzenia używają nowego typu wywołania zwrotnego TsgcWSPusherMemberEvent, który dostarcza nazwę kanału, ID użytkownika i informacje o nim jako osobne parametry:

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

Używa nowego typu wywołania zwrotnego TsgcWSPusherSubscriptionCountEvent. To zdarzenie wymaga włączenia funkcji Subscription Count w ustawieniach panelu 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

Używa nowego typu wywołania zwrotnego TsgcWSPusherCacheMissEvent. To zdarzenie jest wywoływane przy subskrypcji kanału cache (cache-, private-cache-, private-encrypted-cache- lub presence-cache-), gdy nie ma dostępnego zbuforowanego zdarzenia.

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. Nowe metody REST API

Do komponentu TsgcWS_API_Pusher dodano dwie nowe metody REST API po stronie serwera, obejmujące punkt końcowy zdarzeń wsadowych i zakończenie połączeń użytkownika.

Metoda Pusher Endpoint Opis
TriggerBatchEvents POST /apps/{app_id}/batch_events Wyzwala do 10 zdarzeń w jednym żądaniu HTTP. Każde zdarzenie może trafiać do innego kanału.
TerminateUserConnections POST /apps/{app_id}/users/{user_id}/terminate_connections Kończy wszystkie połączenia WebSocket dla określonego uwierzytelnionego użytkownika.

TriggerBatchEvents

function TriggerBatchEvents(const aBatch: String): String;

Parametr aBatch to ciąg JSON zawierający tablicę batch obiektów zdarzeń. Każdy obiekt musi zawierać channel, name i data. Maksymalnie 10 zdarzeń na wsad.

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;

Wymusza zakończenie wszystkich aktywnych połączeń WebSocket dla danego użytkownika. Przydatne do wylogowywania użytkownika na wszystkich jego urządzeniach lub cofania dostępu po zmianie uprawnień. Wymaga skonfigurowania uwierzytelniania użytkowników Pusher.

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

4. Zaktualizowane metody REST API

Trzy istniejące metody REST API zostały rozszerzone o dodatkowe opcjonalne parametry. Ponieważ nowe parametry mają wartości domyślne, istniejący kod jest w pełni wstecznie zgodny.

TriggerEvent

Poprzednia sygnatura

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

Nowa sygnatura

function TriggerEvent(const aEventName, aChannel, aData: String;
  const aSocketId: String = '';
  const aInfo: String = ''): String;
Parametr Opis
aSocketId Wyklucza to ID gniazda z odbierania zdarzenia. Przydatne do zapobiegania, aby nadawca nie odbierał własnej transmisji.
aInfo Rozdzielona przecinkami lista atrybutów do zwrócenia. Prawidłowe wartości: 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

Poprzednia sygnatura

function GetChannels: String;

Nowa sygnatura

function GetChannels(
  const aFilterByPrefix: String = '';
  const aInfo: String = ''): String;
Parametr Opis
aFilterByPrefix Filtruje zwracane kanały według prefiksu nazwy. Przykład: presence- zwraca tylko kanały presence.
aInfo Atrybuty rozdzielone przecinkami. Prawidłowe wartości: user_count (tylko 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

Poprzednia sygnatura

function GetChannel(const aChannel: String): String;

Nowa sygnatura

function GetChannel(const aChannel: String;
  const aInfo: String = ''): String;
Parametr Opis
aInfo Atrybuty rozdzielone przecinkami. Prawidłowe wartości: 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. Poprawki błędów

Several bugs were identified and corrected in this release:

Błąd Wpływ Poprawka
Typo in DoReadEvent: 'puserh:ping' Krytyczny Pingi serwera nigdy nie były rozpoznawane, co powodowało pomijanie żądań heartbeat przez klienta i mogło skutkować rozłączeniem klienta przez serwer z powodu braku aktywności. Poprawiono na 'pusher:ping'.
DoSendPong null access Wysoki Dostęp do JSON.Node['data'].Value bez sprawdzenia null mógł powodować naruszenie dostępu, gdy wiadomość ping nie miała pola data. Dodano sprawdzenie null; domyślnie {} gdy brak pola data.
GetUsers hardcoded prefix Wysoki Metoda zawsze dodawała prefiks presence- do nazwy kanału, podwajając go gdy użytkownik podał już pełną nazwę (np. presence-presence-room). Usunięto stały prefiks. Użytkownicy powinni teraz podawać pełną nazwę kanału wraz z prefiksem presence-.
GetUsers double semicolon Niski Na końcu metody znajdował się zbędny podwójny średnik ;;. Usunięto dodatkowy średnik.

Zmiana niekompatybilna w GetUsers: Metoda GetUsers nie dodaje już automatycznie prefiksu presence-. Jeśli twój kod przekazuje tylko nazwę kanału bez prefiksu (np. GetUsers('my-room')), musisz zaktualizować go do pełnej nazwy: GetUsers('presence-my-room').


6. Podsumowanie

Kategoria Liczba Szczegóły
Nowe typy kanałów 2 pscPrivateEncryptedChannel, pscPrivateEncryptedCacheChannel
Nowe zdarzenia WebSocket 4 OnPusherMemberAdded, OnPusherMemberRemoved, OnPusherSubscriptionCount, OnPusherCacheMiss
Nowe metody REST 2 TriggerBatchEvents, TerminateUserConnections
Zaktualizowane metody REST 3 TriggerEvent (+socket_id, +info), GetChannels (+filter, +info), GetChannel (+info)
Nowe właściwości 1 SharedSecret on TsgcWSPusherResponseAuthentication
Poprawki błędów 4 Literówka w ping, dostęp null w pong, prefiks GetUsers, podwójny średnik

Wszystkie zmiany są wstecznie zgodne. Nowe parametry metod mają wartości domyślne, a nowe właściwości zdarzeń są opcjonalne. Jedyną zmianą behawioralną jest GetUsers, który nie dodaje już automatycznie prefiksu presence-.