# Horse Streaming

> Diretrizes e workflows para desenvolvimento e manutenção de transmissões de dados em tempo real (Web Streams e Server-Sent Events - SSE) no framework Horse.

- Skill: `hashload/horse-streaming` (Agent Skill)
- Install (CLI): `npx skillmds@latest add hashload/horse-streaming`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hashload/horse-streaming/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: hashload (https://skillmd.com/u/hashload)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/hashload/horse-streaming

---


# Horse Streaming Development Guide

Esta skill guia o desenvolvimento, depuração e manutenção de fluxos de streaming de dados (Web Streams / SSE) no framework Horse.

## 🟢 Conceitos Fundamentais
*   **Web Streams (NDJSON)**: Envio de dados formatados como múltiplos JSONs delimitados por quebras de linha (`\n`), utilizando o cabeçalho `Transfer-Encoding: chunked`.
*   **Server-Sent Events (SSE)**: Fluxo unidirecional persistente onde o servidor envia eventos estruturados sob o formato `event: message\ndata: ...\n\n` com o Content-Type `text/event-stream`.

## 🟢 Como usar nas Rotas do Horse
Para enviar dados via streaming, o manipulador da rota deve definir o `ContentType` adequado e invocar o `Res.SendStream`:

```delphi
  THorse.Get('/stream',
    procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
    begin
      Res.ContentType('application/x-ndjson; charset=utf-8');
      Res.SendStream(
        procedure(const AWriter: IHorseStreamWriter)
        begin
          if AWriter.IsConnected then
            AWriter.Write('{"data": "teste"}'#10);
        end);
    end);
```

## 🟢 Implementação dos Provedores Físicos
Ao criar ou estender novos provedores lógicos de transporte no Horse:
1.  Deve-se herdar uma classe especializada de `THorseStreamWriterBase` e implementar os métodos `Write` (escrita física), `IsConnected` (validação física de conectividade do socket) e `Close` (fim de transmissão/descarregamento de buffers).
2.  Registrar a fábrica através de `THorseResponse.RegisterStreamWriterFactory(Factory)`.

## 🟢 Peculiaridades por Provedor

### Indy (`TIdHTTPAppResponse`)
*   **Conexão**: A thread física é acessada via o campo `FThread` da Friend Class.
*   **Envio de Headers**: Invocar `MoveCookiesAndCustomHeaders` do `TIdHTTPAppResponse` para carregar headers customizados e cookies antes do `WriteHeader`.
*   **Flag de Envio**: Marcar `FSent := True` no `TIdHTTPAppResponse` para impedir que o WebBroker dispare novamente os headers no fim do dispatcher.
*   **Bypass de HTML do Indy**: Preencher `ContentStream` com um `TMemoryStream` vazio, `FreeContentStream := True` e `ContentLength := 0` para desativar a injeção do HTML default de 200 OK de 39 bytes pelo Indy.

