Horse WebSocket Coding Skill
This skill provides guidelines and patterns for developers and AI agents implementing, debugging, or maintaining WebSocket endpoints in the Horse framework.
🟢 Request Upgrade Pattern
To upgrade an HTTP request to a WebSocket connection, always call Res.UpgradeToWebSocket(AOnConnectCallback) inside the route handler.
Delphi Syntax (Anonymous Procedure / Closure)
THorse.Get('/ws',
procedure(Req: THorseRequest; Res: THorseResponse)
begin
Res.UpgradeToWebSocket(
procedure(const AConn: IHorseWebSocketConnection)
begin
AConn.OnMessage := procedure(const AConnection: IHorseWebSocketConnection; const AText: string)
begin
AConnection.SendText('Received: ' + AText);
end;
end);
end);
Lazarus/FPC Syntax (Object Methods)
Always use regular object methods or class procedures for callbacks in Lazarus/FPC to ensure compatibility:
type
TWebSocketController = class
public
class procedure HandleWS(Req: THorseRequest; Res: THorseResponse);
class procedure OnConnect(const AConn: IHorseWebSocketConnection);
class procedure OnMessage(const AConnection: IHorseWebSocketConnection; const AText: string);
end;
class procedure TWebSocketController.HandleWS(Req: THorseRequest; Res: THorseResponse);
begin
Res.UpgradeToWebSocket(OnConnect);
end;
class procedure TWebSocketController.OnConnect(const AConn: IConn);
begin
AConn.OnMessage := OnMessage;
end;
class procedure TWebSocketController.OnMessage(const AConnection: IHorseWebSocketConnection; const AText: string);
begin
AConnection.SendText('Received: ' + AText);
end;
🟢 Broadcasts and Session Management
Use THorseWebSocketManager for thread-safe operations across multiple connections.
- Broadcast to all:
THorseWebSocketManager.Broadcast('/ws', 'Hello all!'); - Broadcast excluding sender:
THorseWebSocketManager.Broadcast('/ws', 'Hello others!', AConnection);
🟢 Error and Exception Handling
- Silencing normal interruptions: Normal connection validation errors or manual status sends followed by pipeline interruption should raise
EHorseCallbackInterrupted(from unitHorse.Exception.Interrupted) to gracefully exit the middleware pipeline. - Callback Safety: Always place try-except blocks inside custom event handlers (like
OnMessage) to prevent crashes inside the worker socket threads. - Fail-Fast Detection: If a client requests a WebSocket upgrade on an unsupported provider (e.g.
HttpSysor hosted ISAPI/CGI),Res.UpgradeToWebSocketwill automatically reply with501 Not Implementedand raiseEHorseCallbackInterrupted.
🟢 Thread-Safety Rules
IHorseWebSocketConnection.SendTextandSendBinaryare thread-safe and protected by an internalTCriticalSection. Do not add manual synchronization wrappers around them.- The HTTP request/response objects (
THorseRequest,THorseResponse) are recycled/destroyed once the upgrade is completed. Do not store or reference them inside any of the WebSocket callbacks (OnMessage,OnDisconnect, etc.). Use theIHorseWebSocketConnectioncontext instead.