In this article, a server application uses the Indy HTTP server to provide a HTML page which uses SSE to update its content with data sent from the server.
Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection, and describes how servers can initiate data transmission towards clients once an initial client connection has been established.
Server-sent events, https://en.wikipedia.org/w/index.php?title=Server-sent_events&oldid=1093881969 (last visited Sept. 17, 2022).
Part 1: a very basic demo application
Ingredient #1: a HTML page with Javascript
<!DOCTYPE html> <html> <head> <title>SSE example</title> </head> <body> <script> const evtSource = new EventSource("sse"); evtSource.addEventListener("ping", (event) => { const newElement = document.createElement("li"); const eventList = document.getElementById("list"); const time = JSON.parse(event.data).time; newElement.textContent = `ping at ${time}`; eventList.appendChild(newElement); }); </script> <ul id="list"> </ul> </body> </html>
The code is based on the article Using server-sent events on MDN
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
Ingredient #2: server side code
In the example application, a TIdHTTPServer subclass is used to deliver the HTML document when a browser accesses it.
Note that the server has to keep connections alive, so the Server property KeepAlive must be set to true:
procedure Test; begin Server := TMySSEServer.Create; try Server.KeepAlive := True; Server.Startup; ReadLn; finally Server.Free; end; end;
The DoCommandGet method is overriden and looks like this:
procedure TMySSEServer.DoCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var S: TStream; C: string; begin if ARequestInfo.Document = '/sse' then begin AResponseInfo.ContentType := 'text/event-stream'; AResponseInfo.CacheControl := 'no-store'; AResponseInfo.CharSet := 'UTF-8'; C := 'event: ping' + #13 + Format('data: {"time": "%d"}', [GetTickCount]) + #13#13; AResponseInfo.ContentText := C; AResponseInfo.ResponseNo := 200; end else begin S := TFileStream.Create('index.html', fmOpenRead); AResponseInfo.ContentType := 'text/html'; AResponseInfo.ContentStream := S; AResponseInfo.ResponseNo := 200; end; end;
Output

When the browser navigates to http://localhost
, the server will provide the HTML and the embedded JavaScript will start reading data from the address http://localhost/sse
(and receive only one event). As specified in the HTML spec for EventSource, the client will retry after some seconds:
Each
HTML – 9.2 Server-sent events (https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events)EventSource
object has the following associated with it:
– A reconnection time, in milliseconds. This must initially be an implementation-defined value, probably in the region of a few seconds.
Note: this is just the first step. In the next part, we will implement a continuos data stream.
Discover more from Habarisoft Blog
Subscribe to get the latest posts sent to your email.