Created
November 2, 2012 21:05
-
-
Save tpitale/4004298 to your computer and use it in GitHub Desktop.
Reel-based SSE server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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