API Pusher

Pusher

O Pusher é uma plataforma fácil e confiável com bons recursos baseados no protocolo WebSocket: mensageria pub/sub flexível, listas de usuários ao vivo (presence), autenticação...

A versão da API WebSocket do Pusher é 7.

Os dados são enviados bidirecionalmente sobre um WebSocket como dados de texto contendo JSON codificado em UTF8 (frames WebSocket binários não são suportados).

Você pode chamar o método Ping para testar a conexão com o servidor. Essencialmente, quaisquer mensagens recebidas da outra parte são consideradas como indicação de que a conexão está ativa. Na ausência de qualquer mensagem, qualquer uma das partes pode verificar se o outro lado está respondendo enviando uma mensagem de ping, à qual a outra parte deve responder com um pong.

Antes de conectar, você deve preencher os seguintes campos:


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

O Pusher exige que o cliente websocket conecte a uma URL usando os campos anteriores (key, cluster...), esses campos são usados para construir a url e isso é feito quando você atribui o cliente no componente pusher. Portanto, para ter certeza de que a URL é construída corretamente, defina o cliente depois de ter preenchido os campos de configuração do pusher. Veja abaixo o pseudocódigo:

// configure pusher fields

pusher.cluster = ...

pusher.key = ...

// set client

pusher.client = websocket client

// start connection

websocket client.Active = true;

Após uma conexão bem-sucedida, o evento OnPusherConnect é gerado e você obtém os seguintes campos:

Em caso de erro, OnPusherError será gerado e informações sobre o erro serão fornecidas. Um erro pode ser enviado pelo Pusher em resposta a autenticação inválida, um comando inválido, etc.

4000-4099

Indica um erro que resulta no fechamento da conexão pelo Pusher, e que tentar reconectar com os mesmos parâmetros não terá sucesso.

4000: O aplicativo aceita apenas conexões SSL, reconecte usando wss://

4001: A aplicação não existe

4003: Aplicação desabilitada

4004: A aplicação excedeu a cota de conexão

4005: Caminho não encontrado

4006: Formato de string de versão inválido

4007: Unsupported protocol version

4008: Nenhuma versão de protocolo fornecida

4100-4199

Indica um erro que resulta no fechamento da conexão pelo Pusher, e que o cliente pode reconectar após 1s ou mais.

4100: Capacidade excedida

4200-4299

Indica um erro que resulta no fechamento da conexão pelo Pusher, e que o cliente pode reconectar imediatamente.

4200: Reconexão genérica imediata

4201: Resposta Pong não recebida: o ping foi enviado ao cliente, mas nenhuma resposta foi recebida - veja as mensagens ping e pong

4202: Fechado após inatividade: O cliente esteve inativo por um longo período (atualmente 24 horas) e o cliente não suporta ping. Atualize para um rascunho WebSocket mais recente ou implemente a versão 5 ou superior deste protocolo.

4300-4399

Qualquer outro tipo de erro.

4301: Evento de cliente rejeitado devido ao rate limit

Canais

Os canais são um conceito fundamental no Pusher. Cada aplicação tem uma série de canais, e cada cliente pode escolher em quais canais se inscreve.

Os canais fornecem:

É altamente recomendável que os canais sejam usados para filtrar seus dados e que isso não seja feito usando eventos. Isso ocorre porque todos os eventos publicados em um canal são enviados a todos os assinantes, independentemente de seu vínculo de evento.

Os canais não precisam ser criados explicitamente e são instanciados sob demanda do cliente. Isso significa que criar um canal é fácil. Basta instruir um cliente a assiná-lo.

Os seguintes tipos de canais são suportados:

Canais Públicos

Canais públicos devem ser utilizados para dados acessíveis publicamente, pois não exigem nenhuma forma de autorização para serem assinados.

Você pode assinar e cancelar a assinatura de canais a qualquer momento. Não há necessidade de esperar o Pusher terminar de conectar primeiro.

Exemplo: assinar o canal "my-channel".


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

Se você assinar com sucesso, o evento OnPusherSubscribe será gerado; se houver um erro, você receberá uma mensagem no evento OnPusherError.

Todas as mensagens do canal assinado serão recebidas no evento OnPusherEvent.

Quando o método Publish é chamado e o canal é Público, o componente, em vez de utilizar o protocolo WebSocket, utiliza o protocolo HTTP e chama o método TriggerEvent (a publicação não é permitida utilizando o protocolo websocket).

Private Channels

Requer Indy 10.5.7 ou posterior

Canais privados devem ser utilizados quando o acesso ao canal precisa ser restrito de alguma forma. Para que um usuário possa assinar um canal privado, a permissão deve ser autorizada.

Exemplo: assina o canal "my-private-channel".


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

Se você assinar com sucesso, o evento OnPusherSubscribe será gerado; se houver um erro, você receberá uma mensagem no evento OnPusherError.

Todas as mensagens do canal assinado serão recebidas no evento OnPusherEvent.

Canais de presença

Requer Indy 10.5.7 ou posterior

Os canais Presence se baseiam na segurança dos canais Private e expõem o recurso adicional de ter ciência de quem está inscrito naquele canal. Isso torna extremamente fácil construir funcionalidades de sala de chat e do tipo "quem está online" na sua aplicação. Pense em salas de chat, colaboradores em um documento, pessoas vendo a mesma página web, competidores em um jogo, esse tipo de coisa.

Os canais de presença são assinados a partir da API do cliente da mesma forma que os canais privados, mas o nome do canal deve ser prefixado com presence-. Assim como nos canais privados, uma requisição HTTP é feita a uma URL de autenticação configurável para determinar se o usuário atual tem permissões para acessar o canal.

As informações sobre os usuários que se inscrevem e cancelam a inscrição em um canal podem então ser acessadas vinculando-se a eventos no presence channel, e o estado atual dos usuários inscritos no canal está disponível por meio da propriedade channel.members.

Example: assina o canal "my-presence-channel".


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

Se você assinar com sucesso, o evento OnPusherSubscribe será gerado; se houver um erro, você receberá uma mensagem no evento OnPusherError.

Todas as mensagens do canal assinado serão recebidas no evento OnPusherEvent.

Cache Channels

Um canal de cache lembra o último evento disparado e o envia como o primeiro evento a novos assinantes.

Quando um evento é acionado em um canal de cache, o Pusher Channels armazena esse evento em cache e, quando um cliente assina um canal de cache, se existir um valor em cache, este é enviado ao cliente como o primeiro evento naquele canal. Esse comportamento ajuda os desenvolvedores a fornecer o estado inicial sem adicionar lógica adicional para buscá-lo em outro lugar.

Os seguintes Cache Channels são suportados:

Exemplo: assinar o canal de cache público "my-cache-channel".


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

Se você assinar com sucesso, o evento OnPusherSubscribe será gerado; se houver um erro, você receberá uma mensagem no evento OnPusherError.

Todas as mensagens do canal assinado serão recebidas no evento OnPusherEvent.

Se não houver evento em cache ao assinar um canal de cache, o evento OnPusherCacheMiss será gerado, fornecendo o nome do canal. Isso permite que sua aplicação trate o caso em que nenhum dado em cache está disponível.

Private-Encrypted Channels

Os canais Private-Encrypted fornecem criptografia de ponta a ponta para as mensagens. Como os canais privados, eles exigem autenticação, mas, adicionalmente, todas as cargas úteis de dados são criptografadas usando NaCl secretbox, de modo que apenas assinantes autorizados possam ler o conteúdo. Nem mesmo a própria Pusher consegue descriptografar as mensagens.

Para utilizar canais privados-criptografados, você deve fornecer um SharedSecret durante a autenticação. O segredo compartilhado é utilizado para criptografar e descriptografar os dados da mensagem.

Exemplo: inscreva-se em um canal privado criptografado "my-encrypted-channel".


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

Também está disponível uma variante private-encrypted-cache, combinando criptografia com o comportamento de canal de cache:


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

Ao usar o evento OnPusherAuthentication com canais private-encrypted, você pode definir a propriedade SharedSecret no objeto de resposta para fornecer a chave de criptografia:


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

Presence Events

Os canais Presence fornecem eventos adicionais que notificam sua aplicação quando os usuários entram ou saem de um canal, e permitem que você rastreie as contagens de assinaturas.

OnPusherMemberAdded

Gerado quando um novo membro se inscreve em um presence channel. Fornece o nome do canal, o ID do usuário e as informações do usuário do membro que ingressou.


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

OnPusherMemberRemoved

Gerado quando um membro cancela a assinatura de um presence channel. Fornece o nome do canal, o user ID e as informações do usuário do membro que saiu.


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

OnPusherSubscriptionCount

Gerado quando a contagem de inscrições muda em um canal. Fornece o nome do canal e o número atual de assinantes. Este evento deve estar habilitado no seu painel do Pusher.


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

OnPusherCacheMiss

Gerado ao assinar um canal de cache que não tem nenhum evento em cache. Fornece o nome do canal. Isso permite que a sua aplicação trate o caso em que nenhum dado em cache está disponível, por exemplo, buscando os dados de outra fonte.


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

Publicar Mensagens

Você não apenas pode receber mensagens dos canais assinados, mas também pode enviar mensagens a outros usuários assinados.

Chame o método Publish para enviar uma mensagem a todos os usuários assinados do canal.

Exemplo: enviar um evento a todos os usuários inscritos de "my-channel"


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

Publique no máximo 10 mensagens por segundo por cliente (conexão). Quaisquer eventos disparados acima desse limite de taxa serão rejeitados pela Pusher API. Isso não é um problema de sistema, é um problema do cliente. 100 clientes em um canal enviando mensagens nessa taxa teriam, cada um, que processar também 1.000 mensagens por segundo! Embora alguns navegadores modernos possam ser capazes de lidar com isso, muito provavelmente não é uma boa ideia.

REST API

A API está hospedada em http://api-CLUSTER.pusher.com , onde CLUSTER é substituído pelo cluster de seus próprios apps (por exemplo, eu).

Códigos de status HTTP são usados para indicar o sucesso ou não das requisições. Os seguintes status são comuns:

200 Requisição bem-sucedida. O corpo conterá um hash JSON de dados de resposta

400 Erro: detalhes no corpo da resposta

401 Erro de autenticação: o corpo da resposta conterá uma explicação

403 Forbidden: app desabilitado ou acima da cota de mensagens

As seguintes funções da REST API foram implementadas.

Function Descrição
TriggerEvent Dispara um novo evento no canal especificado. Suporta os parâmetros opcionais SocketId (para excluir um cliente) e Info.
TriggerBatchEvents Dispara múltiplos eventos em uma única requisição HTTP. Aceita um array JSON de objetos de evento.
GetChannels Fornece uma lista de todos os canais ativos. Suporta os parâmetros opcionais FilterByPrefix e Info.
GetChannel Fornece informações sobre um canal específico. Suporta um parâmetro Info opcional.
GetUsers Fornece uma lista de todos os usuários conectados a um canal.
TerminateUserConnections Encerra todas as conexões de um determinado usuário pelo seu user ID.

TriggerEvent

Dispara um evento em um ou mais canais. Requer o nome do evento, o nome do canal e o payload de dados.

Parameter Descrição
aEventName O nome do evento a disparar.
aChannel O nome do canal no qual disparar o evento.
aData Os dados do evento (string JSON).
aSocketId (opcional) Um socket ID a excluir do recebimento do evento. Útil para impedir que o remetente receba sua própria mensagem.
aInfo (opcional) Uma lista de atributos separados por vírgula a incluir na resposta (por exemplo, "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

Dispara múltiplos eventos em uma única chamada de API, o que é mais eficiente do que fazer requisições separadas para cada evento. O parâmetro batch deve ser uma string JSON contendo um array de objetos de evento, onde cada objeto tem os campos "channel", "name" e "data".


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

GetChannels

Retorna uma lista de canais ativos. Suporta parâmetros opcionais para filtrar os resultados e solicitar informações adicionais.

Parameter Descrição
aFilterByPrefix (opcional) Filtra os canais por um prefixo de nome (por exemplo, "presence-" para listar apenas canais de presença).
aInfo (opcional) Uma lista de atributos separados por vírgula a incluir na resposta (por exemplo, "user_count").


// get all channels
APIPusher.GetChannels;

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

GetChannel

Retorna informações sobre um canal específico.

Parameter Descrição
aChannel O nome do canal sobre o qual obter informações.
aInfo (opcional) Uma lista separada por vírgulas de atributos a incluir (por exemplo, "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

Retorna uma lista de usuários conectados a um canal de presence. O nome do canal deve incluir o prefixo completo (por exemplo, "presence-my-channel").


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

TerminateUserConnections

Encerra todas as conexões estabelecidas por um determinado usuário. Isso pode ser utilizado para forçar um usuário específico a se desconectar de todos os canais. O ID do usuário deve corresponder ao "user_id" utilizado quando o usuário assinou um canal de presence.


APIPusher.TerminateUserConnections('1234');

Custom Authentication

A Pusher só permite assinar canais privados ou de presença; se a conexão fornecer um token de autenticação, isso permite que você restrinja o acesso.

Você pode construir seu próprio fluxo de Autenticação, utilizando o evento OnPusherAuthentication; este evento é chamado antes de a mensagem de assinatura ser assinada com a chave secreta fornecida pelo Pusher. Este evento possui 2 parâmetros: uma requisição de autenticação com campos como SocketId, nome do canal... que podem ser utilizados pelo seu próprio servidor de autenticação para autenticar ou não a requisição. Encontre abaixo uma captura de tela que mostra o fluxo de autenticação do pusher

Quando um cliente se conecta ao servidor pusher, ele envia a Key fornecida pelo pusher e o servidor retorna um id de identificação (socket_id).

Quando um cliente assina um canal privado (ou de presence), o cliente sgcWebSockets usa a Secret Key fornecida pelo pusher para criar uma assinatura que é incluída na mensagem de assinatura. Usando o evento OnPusherAutentication, você pode capturar os campos necessários para assinar a mensagem, implementar seus próprios métodos de autenticação e, se bem-sucedido, retornar a assinatura, e essa assinatura será incluída na mensagem de assinatura e enviada ao servidor.

Exemplo:


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;

O formato da assinatura é:

Canais privados: key:HMAC256(SocketID, ChannelName)

Canais de presença: key: HMAC256(SocketID, ChannelName, Data)

O objeto TsgcWSPusherResponseAuthentication fornece as seguintes propriedades:

Property Descrição
Secret A chave secreta da Pusher utilizada para computar a assinatura HMAC. Pré-preenchida com Pusher.Secret se configurada.
Assinatura A assinatura de autenticação computada. Se deixada vazia, o componente a calculará automaticamente utilizando o Secret.
SharedSecret A chave secreta compartilhada para canais privados criptografados. Necessária ao se inscrever em pscPrivateEncryptedChannel ou pscPrivateEncryptedCacheChannel. Usada para criptografia de ponta a ponta dos dados da mensagem.