Repository navigation
hubs
Home > Hubs 🚧
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: intermediário
Em uma frase: um hub é uma rota WebSocket com um protocolo pronto: o cliente chama métodos do servidor e recebe a resposta, e o servidor emite eventos para todos, para uma conexão, para um usuário ou para um grupo, inclusive em vários servidores ao mesmo tempo.
Você vai precisar: o pacote RALModuleWebSocketPackage (TRALHubModule na paleta
RAL - Modules, TRALHubClient na RAL - Client); para vários servidores, também o
RALModuleWebSocketMQTTPackage e um broker MQTT (o TRALMQTTBroker do próprio RAL serve).
Hub := TRALHubModule.Create(Self);
Hub.Server := RALIndyServer1;
Hub.Path := '/chat'; // a rota WebSocket
Hub.ClientGroups := True; // o cliente pode entrar e sair de grupos
Hub.Methods.AddMethod('Chat.Send', OnChatSend);
procedure TForm1.OnChatSend(ACall: TRALHubCall);
begin
// args: [sala, texto]
ACall.Hub.EmitToGroup(ACall.ArgAsString(0), 'Chat.Message',
'[' + RALHubQuote(ACall.ArgAsString(1)) + ',' + RALHubQuote(ACall.Connection.User) + ']');
ACall.ReturnJSON('true');
end;-
Methodsé uma coleção do Object Inspector (nome +OnInvoke);OnInvokedo módulo atende o que não está nela. - No método:
ACall.Arg(i)(JSON),ArgAsString(i),ArgCount,Connection; responde comReturnJSON,ReturnTextouFail(mensagem). Uma exceção vira erro para o cliente. -
Emit(evento, args, escopo, chave),EmitToGroup,EmitToUser,EmitExcept; os argumentos são um array JSON em texto ('[1,"a"]'). -
OnConnect/OnDisconnect;Deflate,KeepAliveInterval,MaxMessageSize,AllowedOriginscomo na rota WebSocket.
O módulo serve o cliente JavaScript em <Domain>/ralhub.js; nada para copiar.
<script src="/ralhub.js"></script>
<script>
const hub = new RalHub("/chat");
hub.on("Chat.Message", (texto, autor) => console.log(autor + ": " + texto));
hub.on("$close", code => console.log("caiu", code)); // reconecta sozinho
hub.start()
.then(() => hub.join("geral"))
.then(() => hub.invoke("Chat.Send", "geral", "olá"));
</script>invoke devolve uma Promise (resultado ou erro); send chama sem esperar resposta;
stop() encerra sem reconectar. Opções: new RalHub(url, {reconnect, reconnectDelay, reconnectMaxDelay, timeout, protocols}).
HubClient := TRALHubClient.Create(nil);
HubClient.URL := 'ws://localhost:8090/chat';
HubClient.OnHubEvent := OnEvento; // (ASender, ATarget, AArgs)
HubClient.Connect;
HubClient.JoinGroup('geral');
Resultado := HubClient.Invoke('Chat.Send', '["geral","olá"]'); // espera InvokeTimeoutÉ um TRALWebSocketClient: herda TLS, proxy, autenticação e reconexão. Invoke pode ser
chamado da thread principal mesmo com SyncEvents (ele deixa os eventos rodarem
enquanto espera).
Atrás de um balanceador, cada usuário fica num servidor. Com um TRALHubMQTTBackplane
ligado ao hub, todo Emit vai também para os outros servidores pelo broker, e cada um
entrega às suas conexões:
Mqtt := TRALMQTTClient.Create(Self);
Mqtt.Host := 'broker.interno';
Mqtt.Port := 1883;
Backplane := TRALHubMQTTBackplane.Create(Self);
Backplane.Client := Mqtt;
Backplane.Hub := Hub; // o tópico é ralhub/<nome do hub>Ao ativar o servidor o cliente conecta (se não estava) e assina o tópico; ao parar, sai.
Channel muda o nome do tópico (os servidores do mesmo cluster usam o mesmo). O
EmitExcept e as respostas de Invoke ficam só no servidor local.
Uma mensagem de texto, um objeto JSON:
| sentido | mensagem |
|---|---|
| cliente → servidor |
{"t":"invoke","id":1,"target":"Chat.Send","args":["geral","olá"]} (sem id: ninguém espera a resposta) |
| servidor → cliente |
{"t":"result","id":1,"result":true} ou {"t":"error","id":1,"error":"mensagem"}
|
| servidor → cliente | {"t":"event","target":"Chat.Message","args":["olá","ana"]} |
Com ClientGroups, os alvos hub.join e hub.leave (args: [grupo]) põem e tiram o
próprio cliente de um grupo.
- WebSocket, Broker MQTT, Balanceador.
- Exemplo:
PascalRAL-Samples,Delphi/Console/WebSocketExample(página de chat comralhub.js).
Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- JSON-RPC 2.0 🚧
- Servidor MCP (IA) 🚧
-
Protocol Buffers 🚧
- gRPC 🚧
- WebSocket 🚧
- Hubs (WebSocket) 🚧
- Swagger e Postman
- Servidor SOAP 🚧
- WS-Security 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
E-mail 🚧
- Mensagens 🚧
- Enviar 🚧
- Receber 🚧
- Ler a caixa postal 🚧
- Verificar o que chega 🚧
- Servir caixas postais 🚧
- S/MIME 🚧
- OpenPGP 🚧
Chatbot 🚧
Cliente
Motores
- Qual motor escolher?
- Compatibilidade
- Recursos
- QUIC
- Motor NgHttp2 (HTTP/2) 🚧
- Motor XSocket 🚧
- Motor AdvancedHTTP (experimental) 🚧
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar