Skip to content

Instantly share code, notes, and snippets.

@tpitale
Created November 2, 2012 21:05
Show Gist options
  • Save tpitale/4004298 to your computer and use it in GitHub Desktop.
Save tpitale/4004298 to your computer and use it in GitHub Desktop.
Reel-based SSE server
require 'reel'
require 'json'
class SSE
def initialize(io)
@io = io
end
def write(object, options={})
options.each do |k,v|
@io.write "#{k}: #{v}\n"
end
@io.write "data: #{JSON.dump(object)}\n\n"
end
def close
@io.close
end
end
class WebServer < Reel::Server
include Celluloid::Logger
def initialize(host = "127.0.0.1", port = 3000)
info "SSE example starting on #{host}:#{port}"
super(host, port, &method(:on_connection))
end
def on_connection(connection)
while request = connection.request
info "Client requested: #{request.method} #{request.url} #{request.query_string}"
case request.url
when "/"
render_index(connection)
when "/time"
stream!(connection)
else
render_not_found(connection)
end
info "Finished handling connection"
end
end
def stream(connection)
connection.detach
headers = {'Content-Type' => 'text/event-stream', 'Transfer-Encoding' => 'chunked'}
connection.respond(:ok, headers)
sse = SSE.new(connection)
begin
now = Time.now.to_f
sleep now.ceil - now + 0.001
loop do
info "Returning current-time: #{Time.now}"
sse.write({:time => Time.now}, :event => 'current-time')
sleep 1
end
rescue IOError, Errno::EPIPE, Errno::ECONNRESET
ensure
info "Closing SSE"
sse.close
end
end
def render_not_found(connection)
info "404 Not Found: /"
connection.respond :not_found
end
def render_index(connection)
info "200 OK: /"
connection.respond :ok, <<-HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Reel SSE time server example</title>
<style>
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
text-align: center;
}
#content {
width: 800px;
margin: 0 auto;
background: #EEEEEE;
padding: 1em;
}
</style>
</head>
<script>
var source = new EventSource('/time');
source.addEventListener('current-time', function(msg) {
console.log(msg);
document.getElementById('current-time').innerHTML = JSON.parse(msg.data).time;
});
</script>
<body>
<div id="content">
<h1>Time Server Example</h1>
<div>The time is now: <span id="current-time">...</span></div>
</div>
</body>
</html>
HTML
end
end
WebServer.supervise_as :reel
sleep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment