Server Sent Events
Server Sent Events (SSE) can be used to push real-time data down to the web browser in an async manner without blocking threads using the IAsyncIEnumerable interface like so:
Endpoint.cs
public class EventStream : EndpointWithoutRequest
{
public override void Configure()
{
Get("event-stream");
AllowAnonymous();
Options(x => x.RequireCors(p => p.AllowAnyOrigin()));
}
public override async Task HandleAsync(CancellationToken ct)
{
//simply provide any IAsyncEnumerable<T> as argument
await SendEventStreamAsync("my-event", GetDataStream(ct), ct);
}
private async IAsyncEnumerable<object> GetDataStream([EnumeratorCancellation] CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(1000);
yield return new { guid = Guid.NewGuid() };
}
}
}
In the browser, the event stream can be subscribed to and consumed using the EventSource object like so:
Index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
const sse = new EventSource('http://localhost:8080/event-stream');
sse.addEventListener('my-event', (e) => console.log(e.data));
</script>
</body>
</html>
If you are planning to create more than a handful of server-sent-event streams, it's a good idea to enable HTTP2 in kestrel and all upstream servers such as reverse proxies and CDNs so that data can be multiplexed between the web server and client using a low number of tcp connections.
Here's a good read on the subject.