81
Transforming Transforming Transforming WebSockets WebSockets WebSockets

Transforming WebSockets

Embed Size (px)

DESCRIPTION

An introduction to WebSockets and why Primus might be a better fit for your project. This presentation was given at WebRebels

Citation preview

Page 1: Transforming WebSockets

TransformingTransformingTransforming

WebSocketsWebSocketsWebSockets

Page 2: Transforming WebSockets

!

3rdEden

"

3rd-Eden

fb

arnout.kazemier

Page 3: Transforming WebSockets
Page 4: Transforming WebSockets
Page 5: Transforming WebSockets

the good partsthe good partsWebSocketsWebSockets

the good partsWebSockets

Page 6: Transforming WebSockets

Chrome 20

Firefox 12

Opera 12.1

Safari 6

Internet Explorer 10

Page 7: Transforming WebSockets

Chrome 4

Firefox 4

Opera 11

Safari 4.2

Internet Explorer 10

Page 8: Transforming WebSockets

oh, it’s bi-directional &

supports binary

oh, it’s bi-directional &

supports binary

oh, it’s bi-directional &

supports binary

Page 9: Transforming WebSockets

The EndThe EndThe End

Page 10: Transforming WebSockets

that nobody told youthat nobody told youthat nobody told youThe partsThe partsThe parts

Page 11: Transforming WebSockets

HTTP proxy settings in your network settings can cause a full browser crash.

Page 12: Transforming WebSockets

user agent sniff

if (! // Target safari browsers! $.browser.safari!! // Not chrome! && !$.browser.chrome!! // And correct WebKit version! && parseFloat($.browser.version, 0) < 534.54!) {! // Don’t use WebSockets!return;!

}

Page 13: Transforming WebSockets

Writing to a closed WebSocket can cause a full browser crash

Page 14: Transforming WebSockets

write crash

var ws = new WebSocket("wss://localhost:8080/");!!ws.onmessage = function message(event) {! // Wrap sends in a setTimeout out to allow the! // readyState to be correctly set to closed. But! // Only have this delay on mobile devices! if (mobile) return setTimeout(function () {! ws.send("Sup Oslo");! }, 0);!! ws.send("Sup Oslo");!};

Page 15: Transforming WebSockets

Pressing ESC in Firefox closes the WebSocket connection

Page 16: Transforming WebSockets

connection end

$('body').keydown(function (e) {! // make sure that you capture the `esc` key and! // prevent it's default action from happening! if (e.which === 27) e.preventDefault();!});

Page 17: Transforming WebSockets

Firefox can create ghost connections when you connect during ws.onclose.

Page 18: Transforming WebSockets

Don’t use self signed SSL certificates, not for development and not in production

Page 19: Transforming WebSockets

4G, 3G, LTE, mobile providers WTF ARE YOU DOING?? — Reverse proxy

Page 20: Transforming WebSockets

Virus scanners such as AVG block WebSockets.

Page 21: Transforming WebSockets

User, network and server firewalls block WebSockets.

Page 22: Transforming WebSockets

Load balancers don't understand and block WebSockets.

Page 23: Transforming WebSockets

So yeah.. Real-Time is HARD

Page 24: Transforming WebSockets

What if…What if…What if…we could change thiswe could change thiswe could change this

Page 25: Transforming WebSockets

Frameworks!Frameworks!Frameworks!

Page 26: Transforming WebSockets

frameworkws

https://github.com/einaros/ws/

super damned fast

supports binary

cross domain

all the cool kids are doing it

i’m the only somewhat maintainer

no fallbacks or downgrading

broken by firewalls/virus scanners

only server, no client

module*

Page 27: Transforming WebSockets

frameworksocket.io

http://github.com/learnboost/socket.io

multiple transports

cross domain

invested with bugs

poorly / not maintained / left for dead

no message order guarantee

dies behind firewall/virusscanners

Page 28: Transforming WebSockets

frameworkengine.io

http://github.com/learnboost/engine.io

supports multiple transports

cross domain

upgrade instead of downgrade

works behind firewalls & virusscanners

not well battle tested yet

no message order guarantee

Page 29: Transforming WebSockets

frameworkbrowserchannelhttps://github.com/josephg/node-browserchannel

multiple transports

client maintained by google

message order guaranteed

works behind firewalls & virusscanners

not cross domain

no websocket support

coffeescript on the server ._.

Page 30: Transforming WebSockets

frameworksockjs

https://github.com/sockjs/sockjs-node/

multiple transports (tons of them)

cross domain

poor error handling

no query string allowed for connect

argh, more coffeescript

connection delay with firewalls

poorly maintained

in the way of developers

Page 31: Transforming WebSockets

They all have different use cases and API's. !

Changing product specs == rewrite

Page 32: Transforming WebSockets

we could change this toowe could change this toowe could change this tooWhat if…What if…What if…

Page 33: Transforming WebSockets

npm install primus

Page 34: Transforming WebSockets

Primus wraps and improves popular real-time frameworks. So you can focus on building apps.

Page 35: Transforming WebSockets

CommunityCommunityCommunity

Page 36: Transforming WebSockets

community

Page 37: Transforming WebSockets

community

Page 38: Transforming WebSockets

1014

15

stars, but growing steadystar it on http://github.com/primus/primus1014

1 line of code to switch betweenexcluding adding a framework to your package.json

different frameworks build-insocket.io, engine.io, sockjs, websockets, browserchannel, but allows addition third party5

1014

15

Page 39: Transforming WebSockets

community

Page 40: Transforming WebSockets

community

Page 41: Transforming WebSockets

5031

5031

50 different pluginssubstream, emit, primus-emitter, primus-cluster, primus-rooms, primus-multiplex, primus-redis

different authorsdamonoehlman, mmalecki, jcrugzz, daffl, balupton, cayasso & many more31

Page 42: Transforming WebSockets

community#primus on irc.freenode.net

questions are bugs, ask them in our github issue tracker

Page 43: Transforming WebSockets

why was primus inventedwhy was primus inventedwhy was primus inventedHistoryHistoryHistory

Page 44: Transforming WebSockets

historyreal-time layer for the bigpipe app framework

Page 45: Transforming WebSockets

historywhich had an engine.io wrapper

Page 46: Transforming WebSockets

historyno single point of failure

Page 47: Transforming WebSockets

historyextracted and released as !

primus

Page 48: Transforming WebSockets

Use casesUse casesUse cases

Page 49: Transforming WebSockets

use cases

module & framework authors

Page 50: Transforming WebSockets

use cases

startups & web developers

Page 51: Transforming WebSockets

Learning PrimusLearning Primus

Learning Primus

Page 52: Transforming WebSockets

learning primus

cd your-awesome-project!!$ npm install --save primus ws!!echo "??" !echo “profit!”!!vim index.js

Page 53: Transforming WebSockets

learning primus

'use strict';!!var Primus = require("primus")! , server = require("http").createServer(fn)! , primus = new Primus(server, { transformer:"ws" });!!primus.on("connection", function connection(spark) {! console.log("connection received", spark.id);! spark.write("ohai");!! spark.on("data", function data(msg) {! console.log("received", msg);! });!});!!server.listen(8080);

Page 54: Transforming WebSockets

learning primus

<script src="http://localhost:8080/primus/primus.js"></script>!<script>!'use strict';!!var primus = new Primus("http://localhost:8080");!!primus.on("open", function connected() {! console.log("connection opened");! primus.write("ohai");!});!!primus.on("data", function data(msg) {! console.log(“received", msg);!});!</script>

Page 55: Transforming WebSockets

SwitchingSwitchingSwitching

Page 56: Transforming WebSockets

1 line of code

var primus = new Primus(server, { ! transformer: “sockjs" // engine.io, socket.io etc!});

Page 57: Transforming WebSockets

1 line of code

Page 58: Transforming WebSockets

1 line of code

module.exports = require(“primus/transformer").extend({! server: function () {! // This is only exposed and ran on the server.! },!! client: function () {! // This is stringified end send/stored in the client.! // Can be ran on the server, if used through Node.js! },!! // Optional library for the front-end, assumes globals! library: fs.readFileSync(__dirname +"./yourclientlib.js")!});

Page 59: Transforming WebSockets

StabilityStabilityStability

Page 60: Transforming WebSockets

manual patching

Page 61: Transforming WebSockets

manual patching

Page 62: Transforming WebSockets

Stream CompatibleStream CompatibleStream Compatible

Page 63: Transforming WebSockets

stream compatible

primus.on("end", function disconnected() {! console.log("connection ended");!});!!primus.end();!primus.write();!!fs.createReadStream(__dirname + '/index.html').pipe(spark, {! end: false!});

Page 64: Transforming WebSockets

EncodingEncodingEncoding

Page 65: Transforming WebSockets

message encoding

var primus = new Primus(server, { ! parser: "JSON" // JSON by default!});

Page 66: Transforming WebSockets

message encoding

var primus = new Primus(server, { ! parser: "EJSON" // or binary-pack or a third party module!});

Page 67: Transforming WebSockets

message encoding

module.exports = {! encoder: function (data, fn) {! // encode data to a string.! },!! decoder: function (data, fn) {! // decode data to an object! },!! // Optional library for the front-end, assumes globals! library: fs.readFileSync(__dirname +"./yourclientlib.js")!};

Page 68: Transforming WebSockets

message encoding

primus.transform('incoming', function (packet) {! // This would transform all incoming messages to foo;! packet.data = 'foo';!});!!primus.transform('outgoing', function (packet) {! // This would transform all outgoing messages to foo;! packet.data = 'foo';!});

transforming

Page 69: Transforming WebSockets

ReconnectReconnectReconnect

Page 70: Transforming WebSockets

reconnect

var primus = new Primus("http://localhost:8080", {! strategy: "disconnect, online"!});

Page 71: Transforming WebSockets

BroadcastBroadcastBroadcast

Page 72: Transforming WebSockets

broadcast

primus.write("message"); // send message to all users!!primus.forEach(function (spark) {! // Or iterate over all connections, select the once you! // want and only write to those!! spark.write("message");!});

Page 73: Transforming WebSockets

Node clientNode clientNode client

Page 74: Transforming WebSockets

node.js

var primus = new Primus(server)! , Socket = primus.Socket;!!var client = new Socket(“http://localhost:8080”);!!// or if you want to connect to a remote server:!var primus = require(“primus”).createSocket({/* options */});

Page 75: Transforming WebSockets

PluginsPluginsPlugins

Page 76: Transforming WebSockets

plugins

// The long awaited Socket.IO 1.0 release with Primus:!!var server = require("http").createServer(fn)! , primus = new Primus(server, { transformer:"engine.io" });!!primus.use(“emitter","primus-emitter")! .use(“multiplex”, require(“primus-multiplex”))! .use(“primus-emitter”, "primus-rooms");

Page 77: Transforming WebSockets

plugins

module.exports = {! server: function () {! // This is only exposed and ran on the server.! },!! client: function () {! // This is stringified end send/stored in the client.! // Can be ran on the server, if used through Node.js! },!! // Optional library for the front-end, assumes globals! library: fs.readFileSync(__dirname +"./yourclientlib.js")!};

Page 78: Transforming WebSockets

and middlewareand middlewareand middlewarePluginsPluginsPlugins

Page 79: Transforming WebSockets

middleware

var server = require("http").createServer(fn)! , primus = new Primus(server, { transformer:"sockjs" });!!primus.before(“session”, require(“session-parse-module”))! .before(“middleware-name”, "middleware-module-name");

Page 80: Transforming WebSockets

!

3rdEden

"

3rd-Eden

fb

arnout.kazemier

That's it! Thanks & check it out on http://primus.io

Page 81: Transforming WebSockets

http://primus.io