em-eventsource - an EventMachine client for Server-Sent Events
- François
About Server-Sent events
With all the buzz around HTML5 and related technologies, some specifications get much more attention than some others. A quite subdued one is the Server-Sent Events spec.
It is also known as EventSource. It allows you to consume a streaming API (aka. streaming server) with a very simple javascript API. On the client side, you’d write something like this:
var source = new EventSource("http://example.com/streaming")
source.onmessage = function(message) {
console.log("got new message:", message.data)
}
The streaming API is made available by example.com/streaming by enforcing a few conventions for the response payloads. The protocol is pretty straightforward:
HTTP1/1 200 OK
Content-Type: text/event-stream
data: my message
data: a new one
It is all about the Content-Type, and streamed (chunked) body. With the previous response, you will have this result in your js debug console:
got new message: my message
got new message: a new one
You can even have a multiline message, with a name.
data: Chuck has joined
data: the meeting room
event: join
You can thus listen for join events:
source.addEventListener("join", function(message) {
console.log("join", message.data)
})
At this point, you should have notice Server-Sent Events is quite different from WebSockets: you don’t have any bidirectonial stream. This is currently the only good way to consume a streaming API in Javascript, with a simple protocol.
Our EventMachine client
Today, we are releasing em-eventsource, a EventMachine client for EventSource. Here’s a use-case:
require "em-eventsource"
EM.run do
source = EventMachine::EventSource.new("http://example.com/streaming")
source.message do |message|
puts "new message #{message}"
end
source.start # Start listening
end
It handles all features of the current specification, except for the line separator, which can only be \n yet.
Why so? Quoting the spec:
Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering with lines are defined to end with a single U+000A LINE FEED (LF) character is safe, block buffering or line buffering with different expected line endings can cause delays in event dispatch.
Apart from this specific point, you can already use the gem and/or convert your old streaming API to a Server-Sent Events compatible one.
About cross-browser compatibility
EventSource is supported by:
- Chrome 9
- Firefox 6
- Opera 11
- Safari 5
You can also use some polyfills like jquery.eventsource if you want.
Have a comment? Contact me by email.