API Pusher

Pusher

Pusher è una piattaforma facile e affidabile con funzionalità interessanti basate sul protocollo WebSocket: messaggistica pub/sub flessibile, liste utenti in tempo reale (presenza), autenticazione...

La versione dell'API WebSocket Pusher è 7.

I dati vengono inviati in modo bidirezionale tramite WebSocket come dati di testo contenenti JSON codificato in UTF8 (i frame WebSocket binari non sono supportati).

È possibile chiamare il metodo Ping per testare la connessione al server. In sostanza, qualsiasi messaggio ricevuto dall'altra parte è considerato un segnale che la connessione è attiva. In assenza di messaggi, entrambe le parti possono verificare che l'altra stia rispondendo inviando un messaggio ping, al quale l'altra parte dovrebbe rispondere con un pong.

Prima di connettersi, è necessario completare i seguenti campi:


Pusher.Cluster := 'eu'; // cluster where your pusher account is located
Pusher.Key := '9c3b7ef25qe97a00116c'; // your pusher api key
Pusher.Name := 'js'; // optional, name of your application
Pusher.Version := '4.1';  // optional, version of your application
Pusher.TLS := True; // if encrypted, set to True
Pusher.Secret := '2dc792e1916ac49e6b3f'; // pusher secret string (needed for private and presence channels)

Importante

Pusher richiede che il client websocket si connetta a un URL usando i campi precedenti (key, cluster...), questi campi sono usati per costruire l'url e ciò avviene quando si assegna il client nel componente pusher. Quindi, per essere sicuri che l'URL sia costruito correttamente, imposti il client dopo aver compilato i campi di configurazione di pusher. Trovi di seguito lo pseudo-codice:

// configura i campi pusher

pusher.cluster = ...

pusher.key = ...

// imposta client

pusher.client = websocket client

// start connection

websocket client.Active = true;

Dopo una connessione riuscita, viene generato l'evento OnPusherConnect e si ottengono i seguenti campi:

In caso di errore, verrà generato OnPusherError con le informazioni sull'errore. Un errore può essere inviato da Pusher in risposta a un'autenticazione non valida, un comando non valido, ecc.

4000-4099

Indica un errore che ha causato la chiusura della connessione da parte di Pusher e che un tentativo di riconnessione con gli stessi parametri non avrà successo.

4000: L'applicazione accetta solo connessioni SSL, riconnettersi utilizzando wss://

4001: L'applicazione non esiste

4003: Applicazione disabilitata

4004: L'applicazione ha superato la quota di connessioni

4005: Percorso non trovato

4006: Formato della stringa di versione non valido

4007: Versione del protocollo non supportata

4008: Nessuna versione di protocollo fornita

4100-4199

Indica un errore che ha comportato la chiusura della connessione da parte di Pusher e che il client può riconnettersi dopo 1 secondo o più.

4100: Capacità esaurita

4200-4299

Indica un errore che ha causato la chiusura della connessione da parte di Pusher, e che il client può riconnettersi immediatamente.

4200: Riconnessione generica immediata

4201: Risposta Pong non ricevuta: è stato inviato un ping al client, ma non è stata ricevuta alcuna risposta - vedere i messaggi ping e pong

4202: Chiuso per inattività: Il client è rimasto inattivo per un lungo periodo (attualmente 24 ore) e non supporta il ping. Aggiornare a una versione più recente di WebSocket o implementare la versione 5 o superiore di questo protocollo.

4300-4399

Qualsiasi altro tipo di errore.

4301: Evento client rifiutato per limite di velocità

Canali

I canali sono un concetto fondamentale in Pusher. Ogni applicazione ha un certo numero di canali, e ogni client può scegliere a quali canali iscriversi.

I canali forniscono:

È fortemente raccomandato utilizzare i canali per filtrare i dati e non farlo tramite gli eventi. Questo perché tutti gli eventi pubblicati su un canale vengono inviati a tutti i sottoscrittori, indipendentemente dal loro binding agli eventi.

I canali non devono essere creati esplicitamente e vengono istanziati su richiesta del client. Ciò significa che creare un canale è semplice. È sufficiente indicare a un client di iscriversi ad esso.

Sono supportati i seguenti tipi di canali:

Canali pubblici

I canali pubblici devono essere utilizzati per dati accessibili pubblicamente in quanto non richiedono alcuna forma di autorizzazione per essere sottoscritti.

È possibile sottoscrivere e annullare la sottoscrizione ai canali in qualsiasi momento. Non è necessario attendere il completamento della connessione di Pusher.

Esempio: sottoscrizione al canale "my-channel".


Delphi
APIPusher.Subscribe('my-channel');

Se la sottoscrizione va a buon fine, verrà generato l'evento OnPusherSubscribe; in caso di errore si riceverà un messaggio nell'evento OnPusherError.

Tutti i messaggi del canale sottoscritto verranno ricevuti nell'evento OnPusherEvent.

Quando viene chiamato il metodo Publish e il canale è Public, il componente, anziché utilizzare il protocollo WebSocket, utilizza il protocollo HTTP e chiama il metodo TriggerEvent (la pubblicazione non è consentita utilizzando il protocollo websocket).

Canali privati

Richiede Indy 10.5.7 o versione successiva

I canali privati devono essere utilizzati quando l'accesso al canale deve essere limitato in qualche modo. Affinché un utente possa iscriversi a un canale privato, l'autorizzazione deve essere verificata.

Esempio: iscrizione al canale "my-private-channel".


Delphi
APIPusher.Subscribe('my-private-channel', pscPrivateChannel);

Se la sottoscrizione va a buon fine, verrà generato l'evento OnPusherSubscribe; in caso di errore si riceverà un messaggio nell'evento OnPusherError.

Tutti i messaggi del canale sottoscritto verranno ricevuti nell'evento OnPusherEvent.

Canali Presence

Richiede Indy 10.5.7 o versione successiva

I canali Presence si basano sulla sicurezza dei canali Private e aggiungono la funzionalità di conoscere chi è iscritto a quel canale. Questo rende estremamente semplice implementare funzionalità di chat room e "chi è online" nella propria applicazione. Si pensi a chat room, collaboratori su un documento, persone che visualizzano la stessa pagina web, concorrenti in un gioco e situazioni simili.

I canali Presence vengono sottoscritti dall'API client nello stesso modo dei canali privati, ma il nome del canale deve essere preceduto dal prefisso presence-. Come per i canali privati, viene effettuata una richiesta HTTP a un URL di autenticazione configurabile per determinare se l'utente corrente dispone delle autorizzazioni per accedere al canale.

Le informazioni sugli utenti che si iscrivono e si disiscrivono da un canale possono essere accessibili associandosi agli eventi sul canale presence, e lo stato corrente degli utenti iscritti al canale è disponibile tramite la proprietà channel.members.

Esempio: sottoscrivi il canale "my-presence-channel".


APIPusher.Subscribe('my-presence-channel', pscPresenceChannel,
  '{"user_id":"John_Smith","user_info":{"name":"John Smith"}}')

Se la sottoscrizione va a buon fine, verrà generato l'evento OnPusherSubscribe; in caso di errore si riceverà un messaggio nell'evento OnPusherError.

Tutti i messaggi del canale sottoscritto verranno ricevuti nell'evento OnPusherEvent.

Canali Cache

Un canale cache ricorda l'ultimo evento generato e lo invia come primo evento ai nuovi sottoscrittori.

Quando un evento viene attivato su un canale cache, Pusher Channels memorizza questo evento nella cache e, quando un client si sottoscrive a un canale cache, se esiste un valore memorizzato nella cache, questo viene inviato al client come primo evento su quel canale. Questo comportamento aiuta gli sviluppatori a fornire lo stato iniziale senza aggiungere logica aggiuntiva per recuperarlo da altrove.

Sono supportati i seguenti canali Cache:

Esempio: sottoscrizione al canale cache pubblico "my-cache-channel".


APIPusher.Subscribe('my-cache-channel', pscCacheChannel);

Se la sottoscrizione va a buon fine, verrà generato l'evento OnPusherSubscribe; in caso di errore si riceverà un messaggio nell'evento OnPusherError.

Tutti i messaggi del canale sottoscritto verranno ricevuti nell'evento OnPusherEvent.

Se non è presente alcun evento memorizzato nella cache al momento della sottoscrizione a un canale cache, verrà generato l'evento OnPusherCacheMiss, fornendo il nome del canale. Ciò consente all'applicazione di gestire il caso in cui non siano disponibili dati memorizzati nella cache.

Canali privati cifrati

I canali Private-Encrypted forniscono la crittografia end-to-end per i messaggi. Come i canali privati, richiedono l'autenticazione, ma in aggiunta tutti i payload di dati vengono crittografati utilizzando NaCl secretbox, in modo che solo i subscriber autorizzati possano leggere il contenuto. Nemmeno Pusher stessa può decrittografare i messaggi.

Per utilizzare i canali privati cifrati, è necessario fornire una SharedSecret durante l'autenticazione. Il segreto condiviso viene utilizzato per cifrare e decifrare i dati dei messaggi.

Esempio: sottoscrizione a un canale privato cifrato "my-encrypted-channel".


APIPusher.Subscribe('my-encrypted-channel', pscPrivateEncryptedChannel);

È disponibile anche una variante private-encrypted-cache, che combina la crittografia con il comportamento del canale cache:


APIPusher.Subscribe('my-encrypted-cache-channel', pscPrivateEncryptedCacheChannel);

Quando si utilizza l'evento OnPusherAuthentication con canali privati cifrati, è possibile impostare la proprietà SharedSecret sull'oggetto di risposta per fornire la chiave di cifratura:


procedure OnPusherAuthenticationEvent(Sender: TObject;
  AuthRequest: TsgcWSPusherRequestAuthentication;
  AuthResponse: TsgcWSPusherResponseAuthentication);
begin
  AuthResponse.SharedSecret := 'your-shared-secret-key';
end;

Eventi di Presenza

I canali Presence forniscono eventi aggiuntivi che notificano all'applicazione quando gli utenti entrano o lasciano un canale, e consentono di monitorare il numero di sottoscrizioni.

OnPusherMemberAdded

Generato quando un nuovo membro si sottoscrive a un canale di presenza. Fornisce il nome del canale, l'ID utente e le informazioni sull'utente del membro che si è unito.


procedure PUSHERPusherMemberAdded(Sender: TObject;
  Channel, UserId, UserInfo: string);
begin
  Log('Member joined: ' + UserId + ' on ' + Channel);
end;

OnPusherMemberRemoved

Viene generato quando un membro si disiscrive da un canale presence. Fornisce il nome del canale, l'ID utente e le informazioni utente del membro che ha abbandonato.


procedure PUSHERPusherMemberRemoved(Sender: TObject;
  Channel, UserId, UserInfo: string);
begin
  Log('Member left: ' + UserId + ' on ' + Channel);
end;

OnPusherSubscriptionCount

Generato quando il conteggio delle sottoscrizioni cambia su un canale. Fornisce il nome del canale e il numero corrente di sottoscrittori. Questo evento deve essere abilitato nella Sua dashboard Pusher.


procedure PUSHERPusherSubscriptionCount(Sender: TObject;
  Channel: string; SubscriptionCount: Integer);
begin
  Log(Channel + ' has ' + IntToStr(SubscriptionCount) + ' subscribers');
end;

OnPusherCacheMiss

Attivato quando ci si sottoscrive a un canale cache che non ha eventi memorizzati nella cache. Fornisce il nome del canale. Questo consente all'applicazione di gestire il caso in cui non siano disponibili dati memorizzati nella cache, ad esempio recuperando i dati da un'altra fonte.


procedure PUSHERPusherCacheMiss(Sender: TObject; Channel: string);
begin
  Log('Cache miss on: ' + Channel);
end;

Pubblicazione di messaggi

Non solo è possibile ricevere messaggi dai canali sottoscritti, ma è anche possibile inviare messaggi ad altri utenti sottoscritti.

Chiamare il metodo Publish per inviare un messaggio a tutti gli utenti sottoscritti al canale.

Esempio: inviare un evento a tutti gli utenti iscritti a "my-channel"


APIPusher.Publish('my-event', 'my-channel');

Pubblichi non più di 10 messaggi al secondo per client (connessione). Qualsiasi evento generato al di sopra di questo limite di rate verrà rifiutato dall'API Pusher. Questo non è un problema del sistema, è un problema del client. 100 client in un canale che inviano messaggi a questa velocità dovrebbero ciascuno anche elaborare 1.000 messaggi al secondo! Sebbene alcuni browser moderni potrebbero essere in grado di gestire questo, è molto probabilmente una cattiva idea.

REST API

L'API è ospitata su http://api-CLUSTER.pusher.com , dove CLUSTER viene sostituito con il cluster della propria app (ad esempio, eu).

I codici di stato HTTP vengono utilizzati per indicare il successo o meno delle richieste. Di seguito sono riportati i codici di stato più comuni:

200 Richiesta riuscita. Il body conterrà un hash JSON di dati di risposta

400 Errore: dettagli nel corpo della risposta

401 Errore di autenticazione: il corpo della risposta conterrà una spiegazione

403 Forbidden: app disabilitata o quota di messaggi superata

Sono state implementate le seguenti funzioni delle API REST.

Funzione Description
TriggerEvent Attiva un nuovo evento sul canale specificato. Supporta i parametri opzionali SocketId (per escludere un client) e Info.
TriggerBatchEvents Genera più eventi in una singola richiesta HTTP. Accetta un array JSON di oggetti evento.
GetChannels Fornisce un elenco di tutti i canali attivi. Supporta i parametri opzionali FilterByPrefix e Info.
GetChannel Fornisce informazioni su un canale specifico. Supporta un parametro Info opzionale.
GetUsers Fornisce un elenco di tutti gli utenti connessi a un canale.
TerminateUserConnections Termina tutte le connessioni di un dato utente tramite il suo ID utente.

TriggerEvent

Attiva un evento su uno o più canali. Richiede il nome dell'evento, il nome del canale e il payload di dati.

Parametro Description
aEventName Il nome dell'evento da attivare.
aChannel Il nome del canale su cui attivare l'evento.
aData I dati dell'evento (stringa JSON).
aSocketId (facoltativo) Un ID socket da escludere dalla ricezione dell'evento. Utile per evitare che il mittente riceva il proprio messaggio.
aInfo (facoltativo) Un elenco separato da virgole di attributi da includere nella risposta (ad es. "subscription_count").


// trigger event on a channel
APIPusher.TriggerEvent('my-event', 'my-channel', 'Hello World');

// trigger event excluding the sender
APIPusher.TriggerEvent('my-event', 'my-channel', 'Hello World', '123.456');

// trigger event requesting subscription_count in the response
APIPusher.TriggerEvent('my-event', 'my-channel', 'Hello World', '', 'subscription_count');

TriggerBatchEvents

Attiva più eventi in una singola chiamata API, il che è più efficiente rispetto all'invio di richieste separate per ogni evento. Il parametro batch deve essere una stringa JSON contenente un array di oggetti evento, dove ogni oggetto ha i campi "channel", "name" e "data".


APIPusher.TriggerBatchEvents(
  '[{"channel":"my-channel","name":"my-event","data":"hello"},' +
  '{"channel":"my-channel-2","name":"my-event","data":"world"}]');

GetChannels

Restituisce un elenco di canali attivi. Supporta parametri opzionali per filtrare i risultati e richiedere informazioni aggiuntive.

Parametro Description
aFilterByPrefix (opzionale) Filtra i canali in base a un prefisso del nome (ad esempio "presence-" per elencare solo i canali presence).
aInfo (facoltativo) Un elenco separato da virgole di attributi da includere nella risposta (ad es. "user_count").


// get all channels
APIPusher.GetChannels;

// get only presence channels with user count
APIPusher.GetChannels('presence-', 'user_count');

GetChannel

Restituisce informazioni su un canale specifico.

Parametro Description
aChannel Il nome del canale di cui si vogliono ottenere informazioni.
aInfo (facoltativo) Un elenco di attributi separati da virgola da includere (ad es. "user_count,subscription_count").


// get channel info
APIPusher.GetChannel('presence-my-channel');

// get channel info with user count
APIPusher.GetChannel('presence-my-channel', 'user_count,subscription_count');

GetUsers

Restituisce un elenco di utenti connessi a un canale presence. Il nome del canale deve includere il prefisso completo (es. "presence-my-channel").


APIPusher.GetUsers('presence-my-channel');

TerminateUserConnections

Termina tutte le connessioni stabilite da un determinato utente. Può essere utilizzato per forzare la disconnessione di un utente specifico da tutti i canali. L'ID utente deve corrispondere allo "user_id" utilizzato quando l'utente si è iscritto a un canale presence.


APIPusher.TerminateUserConnections('1234');

Autenticazione personalizzata

Pusher consente la sottoscrizione solo a canali privati o presence; se la connessione fornisce un token di autenticazione, ciò consente di limitare l'accesso.

È possibile creare un proprio flusso di autenticazione, utilizzando l'evento OnPusherAuthentication; questo evento viene chiamato prima che il messaggio di sottoscrizione venga firmato con la chiave segreta fornita da Pusher. Questo evento ha 2 parametri: una richiesta di autenticazione con campi come SocketId, nome del canale... che possono essere utilizzati dal proprio server di autenticazione per autenticare o meno la richiesta. Di seguito è riportato uno screenshot che mostra il flusso di autenticazione Pusher

Quando un client si connette al server pusher, invia la chiave fornita da pusher e il server restituisce un id di identificazione (socket_id).

Quando un client si iscrive a un canale privato (o presence), il client sgcWebSockets utilizza la Secret Key fornita da pusher per creare una firma che viene inclusa nel messaggio di sottoscrizione. Utilizzando l'evento OnPusherAutentication, è possibile acquisire i campi necessari per firmare il messaggio, implementare i propri metodi di autenticazione e, in caso di successo, restituire la firma che verrà inclusa nel messaggio di sottoscrizione e inviata al server.

Esempio:


oClient := TsgcWebSocketClient.Create(nil);
oPusher := TsgcWSAPI_Pusher.Create(nil);
oPusher.Client := oClient;
oPusher.Cluster := 'eu';
Pusher.Name := 'js';
Pusher.Version := '4.1';
Pusher.TLS := True;
Pusher.Key := '9c3b7ef25qe97a00116c';
Pusher.Secret := ''; // the secret key is not known by the client, only by the authentication module

oPusher.OnPusherAuthentication := OnPusherAuthenticationEvent;

procedure OnPusherAuthenticationEvent(Sender: TObject; AuthRequest: TsgcWSPusherRequestAuthentication;
  AuthResponse: TsgcWSPusherResponseAuthentication);
begin
  // if the authentication request is successful return the signature
  if CustomAuthentication(AuthRequest.Channel, AuthRequest.SocketID) then
    AuthResponse.Signature := GetCustomAuthenticationSignature;
end;

Il formato della firma è:

Canali privati: key:HMAC256(SocketID, ChannelName)

Canali Presence: chiave: HMAC256(SocketID, ChannelName, Data)

L'oggetto TsgcWSPusherResponseAuthentication fornisce le seguenti proprietà:

Proprietà Description
Segreto La chiave segreta Pusher utilizzata per calcolare la firma HMAC. Precompilata con Pusher.Secret se configurata.
Signature La firma di autenticazione calcolata. Se lasciata vuota, il componente la calcolerà automaticamente utilizzando il Secret.
SharedSecret La chiave segreta condivisa per i canali private-encrypted. Obbligatoria quando si sottoscrive pscPrivateEncryptedChannel o pscPrivateEncryptedCacheChannel. Utilizzata per la crittografia end-to-end dei dati dei messaggi.