Class
ServerSentEvents
A Server-Sent Events stream (EventSource in the browser) on a ClientRequest.
Introduction#
Creating it sends the head (200, content-type: text/event-stream, cache-control: no-cache)
and puts it on the wire at once, so the browser sees the stream is open before the first event
exists. The body is chunked on HTTP/1.1 and ends with the connection on HTTP/1.0; each event is
written as one chunk. The stream ends when the handler returns.
A client that leaves makes the next send() or comment() throw phasync\IOException. Let it
leave the handler: swerve ends the exchange without logging, so a loop ends with its client. A
handler that may wait long between events sends a comment now and then, to notice a departure
and to keep proxies from closing the idle stream.
Class synopsis#
final class ServerSentEvents {
/* Methods */
public ServerSentEvents::__construct(ClientRequest $request, array $headers = [])
public ServerSentEvents::lastEventId(): ?string
public ServerSentEvents::send(
string $data,
?string $event = null,
?string $id = null,
?int $retry = null
): void
public ServerSentEvents::comment(string $text = ''): void
}Methods#
| Method | Description |
|---|---|
__construct | Send the head of the stream. |
lastEventId | The Last-Event-ID the client sent when it reconnected: the id of the last event it saw before the connection dropped, or null at its first connection. |
send | Send one event. |
comment | Send a comment: the browser ignores it, so it keeps the stream alive through proxies and lets a handler find out that the client is gone. |
Examples#
use Swerve\ClientRequest;
use Swerve\RequestHandler;
use Swerve\ServerSentEvents;
$app = new RequestHandler(function (ClientRequest $request) {
$events = new ServerSentEvents($request); // the head goes out at once
foreach (['build started', 'tests passed', 'deployed'] as $n => $status) {
phasync::sleep(0.05);
$events->send($status, id: (string) ($n + 1));
}
}); // the stream ends when the handler returns
if (debug_backtrace()) {
return $app; // swerve loads this file: it is the application's swerve.php
}
// Run directly: serve the application with swerve, and send it requests
require __DIR__ . '/../serve.php';
serve(__FILE__, ["GET /deploys HTTP/1.1\r\nHost: example\r\nAccept: text/event-stream\r\n\r\n"]);HTTP/1.1 200 OK content-type: text/event-stream cache-control: no-cache x-accel-buffering: no Server: Swerve Transfer-Encoding: chunked Connection: close 1b id: 1 data: build started 1a id: 2 data: tests passed 16 id: 3 data: deployed 0
return new Swerve\RequestHandler(function (Swerve\ClientRequest $request) {
$sse = new Swerve\ServerSentEvents($request);
foreach (Swerve::subscribe('news', $sse->lastEventId()) as $message) {
$sse->send($message);
}
});