Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial SSE support #456

Merged
merged 2 commits into from
Apr 23, 2020
Merged

Add initial SSE support #456

merged 2 commits into from
Apr 23, 2020

Conversation

yoshuawuyts
Copy link
Member

This adds initial support for Server-Sent Events. It provides both a pre-made endpoint handler, and an upgrade function for use inside manual endpoints. This is the first step towards more elaborate SSE handling. Closes #234.

Future Directions

As described in my tide channels post there are many more things we could do around channels. But those rely on having a notion of identity for connecting clients, which in turn relies on session support. Once we have that we can add persistent connection IDs and more!

Additionally we're not sending automated hearbeat messages yet, I believe we're still missing support for these in http-rs/async-sse.

Screenshots

Screenshot_2020-04-22 tide sse - Rust

@jbr
Copy link
Member

jbr commented Apr 22, 2020

I'm curious about what this would look like in a use case where the events are triggered elsewhere in an application (which I assume is the vast majority of the reason to use SSE). If each connection gets a new async-sse sender/encoder pair, is the idea that within the sse:endpoint fn, users would do something like this?

app.at("/sse").get(sse::endpoint(|req: Request<SomeSharedEventStream>, sender: Sender| async move {
  while let Some(event) = req.state().recv().await {
    sender.send(event.name, event.data_as_u8_slice(), event.id).await;
  }
  Ok(())
}))

@yoshuawuyts
Copy link
Member Author

@jbr as I wrote in my post on Tide Streams we can provide high-level APIs for this, but we first need a notion of identity so we can reliably match incoming requests to existing connections. But what you shared so far could indeed be a way to attempt at building something like that before we fully support it.

@goto-bus-stop
Copy link
Member

I think the id argument to encoder.send() should prob not be hardcoded to None. You need that if you want to implement reconnections correctly without dropping messages, and a future session-based API would likely need to do just that.

In that vein, it might be handy to store the "Last-Event-ID" header value on the sender object, so you can access it easily:

sse::upgrade(req, |req, sse| async move {
  if let Some(event_id /*: &str */) = sse.last_event_id() {
    // handle that
  }
})

That could be a later addition since you can also find it on the req object already.

@yoshuawuyts
Copy link
Member Author

@goto-bus-stop good call! -- I've changed Sender so it now takes an optional third argument of id, matching the API in async-sse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for server-sent events
3 participants