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:
Socket ID: Un identificatore univoco per il client connesso.
Timeout: Il numero di secondi di inattività del server dopo i quali il client deve avviare un messaggio ping (questo è gestito automaticamente dal componente).
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à
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:
Un modo per filtrare i dati. Ad esempio, in un'applicazione di chat, potrebbe esserci un canale per le persone che desiderano discutere di 'cani'
Un modo per controllare l'accesso a diversi flussi di informazioni. Ad esempio, un'applicazione di gestione dei progetti vorrà autorizzare gli utenti a ricevere aggiornamenti su "projectX"
È 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 possono essere sottoscritti da chiunque ne conosca il nome
I canali privati introducono un meccanismo che consente al Suo server di controllare l'accesso ai dati che sta trasmettendo
I canali presence sono un'estensione dei canali privati. Consentono di registrare le informazioni dell'utente al momento dell'iscrizione e permettono agli altri membri del canale di sapere chi è online
I Cache channels ricordano l'ultimo evento attivato e lo inviano come primo evento ai nuovi sottoscrittori (varianti public, private e presence)
I canali privati cifrati forniscono la crittografia end-to-end tramite NaCl secretbox, garantendo che nemmeno Pusher possa leggere i dati del messaggio
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).
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.
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.
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.
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;
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.
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;
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;
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;
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;
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.
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. |
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');
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"}]');
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');
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');
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');
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');
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. |