No desenvolvimento de APIs modernas, a comunicação tradicional baseada em ciclos de requisição e resposta (HTTP tradicional) nem sempre é suficiente. Quando precisamos de atualizações em tempo real com baixíssima latência — como em painéis financeiros, sistemas de chat, telemetria de frotas ou dashboards de monitoramento — os WebSockets se tornam indispensáveis.
Com orgulho, apresentamos a nova especificação e suporte nativo a conexões bidirecionais baseadas no protocolo RFC 6455 (WebSockets) no núcleo e provedores do framework Horse. O suporte foi desenvolvido com foco em alta performance, thread-safety, concorrência e total compatibilidade com Delphi e Lazarus/FPC.
O que são WebSockets e o Desafio da RFC 6455
Diferente de conexões HTTP comuns onde o cliente sempre inicia a requisição, o WebSocket inicia com um aperto de mão (handshake) via requisição HTTP GET especial de “upgrade”. Uma vez aceito pelo servidor, a conexão TCP física é mantida aberta de forma persistente, permitindo que tanto o cliente quanto o servidor enviem mensagens de texto ou binárias a qualquer momento de forma assíncrona.
Para viabilizar isso nativamente no Horse sem dependências externas, implementamos:
- Cálculo de Handshake RFC 6455: Algoritmo que calcula o hash de aceite baseado na chave enviada pelo cliente usando algoritmo SHA-1, compatível de forma nativa com Delphi e FPC.
- Parser & Enquadramento: Decodificação de frames contendo chaves de máscara XOR, payloads fragmentados grandes e controle de opcodes nativos (texto, binário, ping, pong e fechamento).
- Gerenciamento Thread-Safe: Uma infraestrutura baseada em seções críticas para impedir condições de corrida durante escritas paralelas no socket, auxiliada por uma thread nativa de Keep-Alive/Ping.
A Nova API do Horse em Ação
A arquitetura foi projetada para ser extremamente não intrusiva. A elevação de um endpoint tradicional para WebSocket é feita chamando simplesmente o método Res.UpgradeToWebSocket. Veja um exemplo básico de um servidor de chat em Delphi:
program ServidorChat;
{$APPTYPE CONSOLE}
uses
Horse,
Horse.Core.WebSocket;
begin
THorse.Get('/ws',
procedure(Req: THorseRequest; Res: THorseResponse)
begin
// Eleva a conexão HTTP para WebSocket
Res.UpgradeToWebSocket(
procedure(const AConn: IHorseWebSocketConnection)
begin
// Callback acionado quando um novo cliente conecta
Writeln('Novo cliente conectado do IP: ', AConn.GetClientIP);
// Configura escuta de mensagens do cliente
AConn.SetOnMessage(
procedure(const AConnection: IHorseWebSocketConnection; const AText: string)
begin
Writeln('Mensagem recebida: ', AText);
// Faz broadcast da mensagem para todos os outros clientes na rota /ws
THorseWebSocketManager.Broadcast('/ws', 'Anônimo: ' + AText);
end);
AConn.SetOnDisconnect(
procedure(const AConnection: IHorseWebSocketConnection)
begin
Writeln('Cliente desconectado.');
end);
end);
end);
THorse.Listen(9000);
end.
Arquitetura sob o Capô: Desacoplamento via IoC
Para garantir que o suporte a WebSockets funcione de forma idêntica em qualquer provedor do Horse (seja ele baseado em Indy, IOCP no Windows ou Epoll no Linux), implementamos o padrão de Inversão de Controle (IoC) utilizando o container de escopo de requisição nativa do Horse (Req.Services).
Cada provedor físico registra e injeta seu próprio adaptador de I/O (IHorseWebSocketTransport) durante a fase de upgrade. Isso traz dois enormes benefícios:
- Zero Acoplamento Estático: O núcleo de WebSockets não conhece detalhes de I/O do Indy, IOCP ou Epoll. Eles se comunicam puras interfaces.
- Mecanismo Fail-Fast: Se você rodar o Horse em um provedor incompatível (como o HttpSys, que não gerencia o socket físico diretamente), o Horse identificará a ausência do adaptador de upgrade, retornará um status HTTP
501 Not Implementedelegante ao cliente e interromperá a requisição de forma segura, prevenindo vazamentos de memória.
Lazarus, Docker e Suporte Multiplataforma Real
Durante a fase de validação, testamos a compilação cruzada e a execução dos testes unitários e de integração em uma ampla gama de ambientes:
- Delphi 10 Seattle até Delphi 13 Florence (Windows): Preservação total da compatibilidade sem quebras de sintaxe (como remoção de variáveis inline para suportar compiladores clássicos do Delphi).
- Delphi Linux (Linux 64-bit ELF): Compilado com sucesso via linha de comando
dcclinux64.exe. - Lazarus / FPC Linux no Docker: Validação em containers Docker Ubuntu rodando compilador FPC 3.2.2 nativo. Adaptamos as tipagens de socket (
TSocketmapeado dinamicamente paraTHandleno Windows eLongIntno Linux) para garantir compilação limpa em qualquer arquitetura Unix.
Demonstração Prática: Dashboard APM Cyberpunk
Para demonstrar essa funcionalidade em grande estilo, desenvolvemos um Dashboard de Telemetria APM em tempo real. Ele roda como um projeto independente, consumindo métricas do próprio servidor (vazão de requisições por segundo, memória heap e conexões) e as transmitindo a cada 100ms via WebSocket para uma página com design cyberpunk neon e gráficos dinâmicos ApexCharts.
Abaixo você confere o painel em funcionamento durante um teste de carga concorrente (Stress Test) sendo disparado na própria tela:

Como visto no vídeo, a latência do tráfego e renderização dos dados na tela ao ativar o estresse é imperceptível, provando a eficiência absoluta da nossa implementação WebSocket no Horse.
Conclusão e Próximos Passos
Com essa nova feature, o Horse se consolida não apenas como um dos micro-frameworks mais leves e populares da comunidade Delphi/Lazarus, mas como uma solução robusta e moderna para sistemas orientados a eventos assíncronos de alta performance.
O código fonte completo com os adaptadores, testes unitários, manuais e o exemplo do Dashboard APM já está integrado e publicado na branch feature/websocket no repositório oficial do GitHub.
Não deixe de testar, abrir issues com feedbacks e compartilhar o que você construiu usando WebSockets no Horse!
Descubra mais sobre Régys Borges da Silveira
Assine para receber nossas notícias mais recentes por e-mail.
Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.