« Back to Index

Server-Sent Events in Ruby

View original Gist on GitHub

app.rb

require "json"
require "sinatra/base"

class ApplicationController < Sinatra::Base
  helpers ApplicationHelper

  set :views, File.expand_path("../../views", __FILE__)
  set :public_folder, File.expand_path("../../", __FILE__)
  set :server, :thin
  connections = []

  before do
    request.path_info.sub! %r{/$}, ""
  end

  not_found do
    title "Not found!"
    erb :not_found
  end

  error do
    title "Error"
    erb :error
  end

  get "/" do
    erb :home
  end

  get "/status" do
    "ok"
  end

  post "/update" do
    json = request.body.read # can't read `params` as we're not POST'ing key/value pairs

    connections.each do |out|
      out << "id: #{Time.now}\n" +
             "event: ping\n" +
             "data: #{json}\n\n" unless out.closed?
    end
  end

  get "/healthcheck", provides: "text/event-stream" do
    stream :keep_open do |out|
      connections << out

      # `callback` is executed each time a stream connection closes
      out.callback {
        connections.delete(out)
      }
    end
  end
end

client.js

var evtSource = new EventSource("/healthcheck");

evtSource.onmessage = function(e) {
    console.log("onmessage", e.data);
};

evtSource.addEventListener("ping", function(e) {
    console.log("ping", e.data);
}, false);

evtSource.onerror = function(e) {
    console.log("error", e);
};

curl.sh

curl -v -H "Content-Type: application/json" -X POST -d '{"foo":"bar"}' http://127.0.0.1:9292/update