Slide 1

Slide 1 text

Server-Sent Events Luigi Montanez RealtimeConf 2012 For a good realtime...

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Overview Part 1: Why Server-Sent Events? Part 2: Implementing in the browser Part 3: Implementing on the server

Slide 4

Slide 4 text

SPOILER ALERT Server-sent events are the right tool for the job in many scenarios. Try ‘em! You’ll like ‘em!

Slide 5

Slide 5 text

Part 1: Why Server-Sent Events?

Slide 6

Slide 6 text

Problem: Realtime updates on the Web. No page refresh.

Slide 7

Slide 7 text

“Classic” Realtime Solutions AJAX AJAX Polling COMET (Long Polling)

Slide 8

Slide 8 text

“Classic” Realtime Solutions AJAX AJAX Polling COMET (Long Polling)

Slide 9

Slide 9 text

Enter the W3C

Slide 10

Slide 10 text

WebSockets TCP Socket between browser and server Bi-directional

Slide 11

Slide 11 text

Just TCP A lower level than HTTP Developer de!nes protocol Support XMPP, IRC, AMQP, VNC Some proxy servers not compatible

Slide 12

Slide 12 text

No JS Poly!ll Flash-based fallback Socket.IO falls back using di"erent methods

Slide 13

Slide 13 text

Bi-directional communication can be overkill.

Slide 14

Slide 14 text

Server-Sent Events Forgotten little sister of WebSockets

Slide 15

Slide 15 text

The Jan Brady of realtime technologies

Slide 16

Slide 16 text

Server-Sent Events Forgotten little sister of WebSockets Downstream, server to browser push

Slide 17

Slide 17 text

More Bene!ts Just HTTP Browser handles reconnections Pure JS Poly!lls

Slide 18

Slide 18 text

Use Cases Stock ticker Live analytics visualization Twitter-style social feed Triggering noti!cations

Slide 19

Slide 19 text

Part 2: Implementing in the browser

Slide 20

Slide 20 text

A very simple spec

Slide 21

Slide 21 text

In the Browser var source = new EventSource('/stream'); source.addEventListener('message', function(e) { console.log(e.data); }); source.addEventListener('open', function(e) { ... }); source.addEventListener('error', function(e) { ... });

Slide 22

Slide 22 text

Data data: first line data: second line --- data: { data: "id": 12345, data: "msg": "hello world" data: } source.addEventListener('message', function(e) { var obj = JSON.parse(e.data); console.log(obj.id, obj.msg); });

Slide 23

Slide 23 text

ID, Retry, Event id: 123 retry: 10000 data: AAPL data: 572.44 --- data: {"msg": "First message"} event: userlogon data: {"username": "John123"} event: update data: {"username": "John123", "emotion": "happy"} source.addEventListener('userlogon', function(e) { ... source.addEventListener('update', function(e) { ...

Slide 24

Slide 24 text

That’s the entire spec!

Slide 25

Slide 25 text

Browser Support Yes: Firefox, Chrome, Safari, Opera No: Android Browser, Internet Explorer

Slide 26

Slide 26 text

Poly!lls github.com/remy/poly!lls github.com/Ya#e/EventSource github.com/rwldrn/jquery.eventsource

Slide 27

Slide 27 text

CORS Coming Soon var source = new EventSource('elsewhere.com/stream'); Spec in Draft @ W3C Implemented in Firefox & Opera Patch submitted for Webkit

Slide 28

Slide 28 text

Part 3: Implementing on the server

Slide 29

Slide 29 text

Node.js, part 1 var http = require('http'); var sys = require('sys'); var fs = require('fs'); http.createServer(function(req, res) { if (req.headers.accept && req.headers.accept == 'text/event-stream') { if (req.url == '/events') { sendSSE(req, res); } else { res.writeHead(404); res.end(); } } }).listen(8000);

Slide 30

Slide 30 text

Node.js, part 2 function sendSSE(req, res) { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); setInterval(function() { constructSSE(res, ‘time’, (new Date()).toLocaleTimeString()); }, 5000); } function constructSSE(res, event, data) { res.write('event: ' + event + '\n'); res.write("data: " + data + '\n\n'); }

Slide 31

Slide 31 text

Rails 4, part 1 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

Slide 32

Slide 32 text

Rails 4, part 2 require 'sse' class BrowserController < ApplicationController include ActionController::Live def index response.headers['Content-Type'] = 'text/event-stream' sse = SSE.new(response.stream) begin loop do sse.write({ :time => Time.now }) sleep 5 end rescue IOError # When the client disconnects, we'll get an IOError on write ensure sse.close end end end

Slide 33

Slide 33 text

In Closing... When you need a sprinkling of realtime Server-to-browser push Simple, easy-to-implement spec Anti-complexity philosophy

Slide 34

Slide 34 text

Thanks! @LuigiMontanez upworthy.com