18

I'm new to Ruby and Sinatra, I'm trying to setup a simple HTML5 Server-Sent Event with it, The code below works fine in Chrome developer builds but fails in Non Developer Builds and Safari on both Windows7 and OSX.

The error message in the browser console is "Failed to load resource: cancelled"

 var source = new EventSource('pull');
        source.addEventListener('message', function(e) {
            console.log(e.data);

        }, false);

        source.addEventListener('open', function(e) {
            // Conn open
        }, false);

        source.addEventListener('error', function(e) {
            if (e.eventPhase == EventSource.CLOSED) {
                // Connection was closed.
            }
        }, false);

With the below Sinatra route

get '/pull' do
   content_type 'text/event-stream'
   newevent   = false
   response = "data: "+newevent.inspect+" \n\n"
end

I have tried similar server side code with JSP and Tomcat and it works fine on all browser.

What do I need to know about Sinatra? thanks!

Jonas
  • 121,568
  • 97
  • 310
  • 388
user248257
  • 181
  • 1
  • 3
  • 2
    Figured out, I wasnt setting the right response headers, seems like Chrome Dev is more relaxed when it comes to headers. The headers below worked .. response.headers['Content-Type'] = 'text/event-stream' response.headers['Cache-Control'] = 'no-cache' – user248257 Mar 08 '11 at 23:11
  • 2
    That will only return one value and close the connection. What's the advantage over AJAX then? – Konstantin Haase Jun 30 '11 at 17:04

1 Answers1

26

If you want to support events, you have to create your own body object. Take a look at at the implementation and usage. Make sure you run it with Thin or Rainbows. It will not work on Mongrel or WEBrick.

You can watch the presentation at Confreaks (its source code at GitHub).

Update: Here is one more example (Simple Chat Application using the Sinatra Streaming API).

Adam
  • 15,537
  • 2
  • 42
  • 63
Konstantin Haase
  • 25,687
  • 2
  • 57
  • 59
  • 1
    Konstantin, how would you remove closed connections from the list of subscribers? Chrome closes EventSource connection after 60 sec and opens a new one, so that the list is growing. Is there a way to set an infinite timeout for EventSource similar to WebSocket? – Andrei Dec 29 '11 at 20:13
  • Konstantin replied: You can add a `callback/errback` to the body object. You can send null bytes or empty messages if nothing happened within 60 seconds (use EventMachine's timeout events for this). – Andrei Dec 30 '11 at 18:27
  • 6
    See [Writing Good Link Text](http://www.yorku.ca/webacces/simplestrategies/10_linktext.html), "here" is **not** good link text. – Jonas Dec 31 '11 at 13:21
  • More answers and comments on Sinatra with [event streaming](http://stackoverflow.com/questions/3669674/streaming-data-from-sinatra-rack-application) and [WebSockets](http://stackoverflow.com/questions/2999430/any-success-with-sinatra-working-together-with-eventmachine-websockets) – Andrei Dec 31 '11 at 13:30