Cookbook / Realtime
Server-sent events
Push live updates to the browser over a plain HTTP response.
Server-sent events (SSE) are the simplest way to push data to a browser: a long-lived text/event-stream response with automatic reconnection built into EventSource. sse::channel gives you a sender and the response to return.
use axeon::sse::{self, Event};
use axeon::{Html, Server};
use std::time::{Duration, Instant};
const PAGE: &str = r#"<!doctype html>
<h1>Uptime: <span id="t">...</span></h1>
<script>
new EventSource("/events").addEventListener("tick", e => t.textContent = e.data);
</script>"#;
fn main() {
let mut app = Server::new();
app.get("/", |_req| async { Html(PAGE) });
// A clock ticking once per second until the client disconnects.
app.get("/events", |_req| async {
let (tx, response) = sse::channel(8);
tokio::spawn(async move {
let started = Instant::now();
loop {
let event = Event::new().event("tick").data(format!("{}s", started.elapsed().as_secs()));
if tx.send(event).await.is_err() {
break; // the client went away
}
tokio::time::sleep(Duration::from_secs(1)).await;
}
});
response
});
app.listen("127.0.0.1:3000").expect("server failed to start");
}
curl -N http://127.0.0.1:3000/events
Notes#
tx.send(..)fails once the client disconnects. That is your cue to stop the producer task.Eventalso supports.id(..),.retry(..)and.json_data(&value).- On shutdown, event streams are ended cleanly so a deploy never hangs on open connections.