Server-Sent Event Notifications with HTML5 »

Created at: 26.08.2011 22:23, source: igvita.com, tagged: Architecture html5 eventsource sse

Server-Sent Events (SSE) have long been in the shadow of the much more often talked about WebSockets API. While WebSockets can be thought of as the "TCP for the web", then SSE is best described as the "HTML5 replacement for Comet". Question is, do we really need both?

WebSockets allow bi-directional communication and to do so, they piggyback on the original HTTP connection and "upgrade" to the WebSocket protocol. By comparison, and as the name implies, SSE is strictly a server push protocol. Additionally, messages are encoded in UTF-8 and are newline delimited. In other words, the bet is that most applications primarily need to push data to the client, which means that we can simplify the API and the implementation - that is where SSE comes in. Still skeptical? I was. Let's take a look under the hood.

EventSource Client API

Unlike a WebSocket connection, SSE requires no additional HTTP handshakes or "protocol upgrades". For all intents and purposes, an SSE channel is simply a long-lived, streaming HTTP connection. This alone means that you can implement an SSE service on top of any streaming capable HTTP server.

On the browser side, the EventSource API is now supported by Chrome, Firefox 6+, Safari and Opera. To start receiving server notifications, we simply open a connection to an SSE URI and setup our callbacks:

var source = new EventSource('/my/sse_endpoint');
 
source.addEventListener('message', function(e) {
  console.log(e.data);
}, false);
 
source.addEventListener('user_login', function(e) {
  console.log(e.data);
}, false);
 
source.addEventListener('open', function(e) {
  // Connection was opened.
}, false);
 
source.addEventListener('error', function(e) {
  if (e.eventPhase == EventSource.CLOSED) {
    // Connection was closed.
  }
}, false);
 

The API is very simple: create an EventSource connection, define your connection open, close, and message callbacks, and you are off to the races. However, the SSE API also provides a few more built-in features. In the example above we added a "user_login" listener - turns out, we can tag our messages! Likewise, we can provide message ID's, and the SSE source will even automatically reconnect for you if the connection is dropped.

Simple SSE Server with Goliath

The client API is nice and simple, but where the SSE spec really shines is in how simple it makes the server implementation. Whereas to power a WebSocket service you will likely need an entirely different backend, an SSE endpoint can be implemented by any streaming capable HTTP web server. As an example, let's create a Goliath powered SSE app and deploy it to Heroku:

require 'goliath'
 
class EventGenerator < Goliath::API
  def response(env)
    EM.add_periodic_timer(1) { env.stream_send("data:hello ##{rand(100)}\\n\\n") }
    EM.add_periodic_timer(3) do
      env.stream_send(["event:signup", "data:signup event ##{rand(100)}\\n\\n"].join("\\n"))
    end
 
    streaming_response(200, {'Content-Type' => 'text/event-stream'})
  end
end
 
class SSE < Goliath::API
  use Rack::Static, :urls => ["/index.html"], :root => Goliath::Application.app_path("public")
 
  get "/events" do
    run EventGenerator.new
  end
end
 

Our Goliath server responds to requests to /events by returning a 200 OK response, and then starts emitting newline delimited messages every couple of seconds - we're streaming plaintext messages directly into the HTTP connection! Additionally, Goliath also serves a static index file, which opens an EventSource connection to our /events endpoint (see the full gist here). With that, we can add a Procfile and a Gemfile, and push it out to Heroku: a live SSE demo powered by Goliath.

SSE vs. WebSockets

Technically speaking, the WebSockets spec is a superset of SSE and it is easy to wonder why we need both. Having said that, it is also hard not to like the simplicity of the EventSource API - both on the client, and especially on the server. Chances are, many apps won't actually need the bi-directional capabilities of WebSockets, and hence can benefit a great deal from the simplified setup and deployment enabled by SSE. Definitely an option to keep in mind.


more »

Mobile development with HTML5 »

Created at: 26.08.2011 01:54, source: Engine Yard Blog, tagged: Technology html5 jquery local storage mobile

HTML5: the standard, the buzzword and the legend

If you read blogs that are even slightly related to tech, you likely hear about HTML5 on a near-weekly basis. Although the new web standard does not do your laundry, it has features that enable the creation of powerful applications—using only HTML, CSS and JavaScript (a Rails back-end can bring additional firepower to the table). This post will go over some key concepts and features of HTML5, setting the stage for more advanced subjects.

Browser Compatibility

Perhaps the biggest pain in developing a web-based application is ensuring that your application is compatible with the various browsers in use today. Fortunately, this is less of a problem in the mobile world. Because people get new phones more often than new computers and because the smart phone space is relatively young, there are simply fewer old smart phones out in the wild. However, this is not a carte blanche; you should test your site with any devices you wish to support, not just simulators.

Viewport

When you visit a website not designed for mobile browsers, it first appears very zoomed out. This is done intentionally by the mobile browsers to make the website viewable. They set the default viewport width to between 800 and 980 pixels (depending on the browser). This allows the user to view the whole website and then zoom in as needed. However, if you are crafting a website specifically for mobile, it make sense to set the initial viewport for the mobile device. This is accomplished with the viewport meta tag.

<meta name="viewport" content = "width=device-width”>

This sizes the viewport to the device’s width, so the content does not initally appear zoomed out. You will likely want to disable zooming entirely, so the user doesn’t accidentally zoom out and distort the UI. Do this by setting user-scalable to no.

<meta name="viewport" content = "width=device-width ,  user-scalable=no">

Some sites currently hard-code the width of the viewport to 320. Why? Because this is the width of the iPhone. However, in general, it is a better practice to use “device-width” instead of 320.

Having your site correctly sized for mobile is nice but the next two features of HTML5, caching with the cache manifest and local storage, allow for fully functional offline sites.

HTML5 Caching

HTML5 caching allows users to view websites they have visited before without a connection to the web. Not only is this extremely useful for users who may not get coverage where they want to use the application, but it can also mitigate brief drops in a connection.

To setup HTML5 caching, you add a manifest file to the html tag of every page you want to cache.

<html manifest="/cache.manifest">

This file starts with “CACHE MANIFEST” and then enumerates the files that the application should cache.

CACHE MANIFEST
/mystyle.css
/scripts.js
/logo.jpg

Now those files will be available offline. Frankly, there is a long list of gotchas with the cache manifest. I review some key ones below but suggest reading Dive into HTML5 for all the details.

The first and foremost, your site will default to cached files over recently downloaded ones, meaning that even if the cache has changed since the browser has last visited the page, the browser displays the old pages until the page is refreshed (or told with JavaScript to update). This is further compounded by the fact that most web servers tell the browser cache the files they serve. When you are developing your site, be sure to tell your web server not to cache the cache manifest, so you always download the most recent copy.

The next big gotcha is how the browser manages the downloading process. If the browser detects that the manifest has changed, it re-downloads every single file. Not only does this make the process expensive, if a single file fails to download correctly, the browser abandons the update and loads the previous cache. When this happens the browser does not post any error by default. However, you can use JavaScript to detect the error thrown by the manifest.

$(function() {
  $(window.applicationCache).bind("error", function() {
    alert("Cache: update failed");
  });
});

So now your site is cached and everything worked. You’re ready to launch? Not really. This caching technique works well with static content. However, if your application has content that is dynamically created and frequently changed (most web apps), it will not work well. This is because, unless the cache is changed, the old html page will be displayed, not the page with your new content. The simple answer is to change the cache manifest file whenever new content is added. However, this is generally not a good idea because it forces the browser to re-download every file every time any content is changed—very costly if your content is updated frequently. The solution is to use jQuery templates to build the page dynamically.

jQuery Templates

The best practice is to populate your content through JavaScript templates. In this way, the content is not part of the HTML page and thus is not cached with the cache manifest. For this, you need to download and add jQuery and the jQuery template plugin to your application.

There are three steps to using these templates:

  1. Define the template.
  2. Define the collection.
  3. Tell jQuery to populate to the page with the template.

Below is an example for a simple blog application.

1. Define the template:

<script id="post_template" type="text/html”>
<div>

<h2>${Name}</h2>

<p>${Body}</p>

</div>

</script>

2. Define the collection (of posts in JSON).

<script>
var posts = [
{ Name: "First!", Body: "This is pretty cool" },
{ Name: "Another post", Body: "This is pretty cool" },
{ Name: "Yet another blog post", Body: "This is pretty cool" }];
</script>

3. Tell jQueryto populate to the page with the template.

<script>
$( "#post_template" ).tmpl( posts ).appendTo( "#blog_posts" );
</script>

…

<body>

<div id="blog_posts"></div>

</body>

Although this content is loaded via JavaScript, it is not dynamic—it is just defined on the page. For dynamic content we will want to use JSON provided by the server. Let’s assume our blog application provides us with the JSON representation of our blog at this URL:

/posts.json

We will tell jQueryto make a request for the JSON and then use it to populate the page.

<script type="text/javascript">
$.getJSON('/posts.json', function(data) {
$( "#post_template" ).tmpl( data ).appendTo( "#blog_posts" );
});
</script>

We also need to change the template so that it can handle the JSON elements, substituting post.name for Name and post.body for Post:

<script id="post_template" type="text/html">
<div>
  <h2>${post.name}</h2>
  <p>${post.body}</p>
</div>
</script>

Now our blog is pulling content that is not cached in the cache manifest and using jQuery templates to populate the page. However, this works only if our mobile browser can connect to our server. This feels like two steps forward and three steps back, but trust me, we almost have a working mobile HTML5 app. We just need to include one last component of HTML5, Local Storage.

Local Storage

Christopher Haupt of Webvanta recently authored a guest blog post about Local Storage. See the Enhancing Client-side Storage with HTML5 post for details and general use.

On a high level, Local Storage is a client-side key-value store implemented by the browser. It stores strings of text locally and then recalls them later. Here, we use it to store JSON so we can populate the blog with posts even if there is no connection to the server.

Although we could write this by hand, there is a great plugin to manage the process for us. The jQuery Offline plugin uses content from Local Storage if the server is not available and will store fresh content in local storage when it’s received.

Download this plugin from jQuery-Offline

To use the plugin we change the getJSON call to retrieveJSON. We will also need to change our script slightly as there is one key difference between getJSON and retrieveJSON. The latter will execute twice, once to pull from the cache and again to get the new content from the server. This will cause the posts to appear twice if we simply append the new posts to the page.

<script type="text/javascript">
$.retrieveJSON('/posts.json', function(data) {
$( "#blog_posts" ).html($( "#post_template" ).tmpl( data ));

});
</script>

The blog application can now be viewed offline and is correctly sized for a mobile browser! You can download this example here offline-blog.

I hope you enjoyed this initial look at some of the technologies that are making mobile development easier. In the coming weeks I hope to be covering more advanced topics such as the popular MVC framework Backbone.js.


more »

HTML5 Visibility API & Page Pre-Rendering »

Created at: 25.06.2011 21:04, source: igvita.com, tagged: html5 chrome prerendering webkit

Minimizing UI latency is critical for creating a positive user experience - this is true both on the desktop and on the web. A best practice for a "native app" is to decouple the UI and control threads to avoid blocking on any long-running tasks. On the web, things are a lot trickier: our Javascript runtimes are all single-threaded, we can't just spin up an extra thread, and instead have to rely on event-driven programming models. Even worse, unless the invoked computation is local, a roundtrip to the server can easily take hundreds of milliseconds in the network overhead alone.

Not surprisingly, over the course of the past few years we have invented dozens of new Javascript based UI frameworks: all asynchronous, all focused on trying to hide the interaction latency behind a Javascript facade. In theory, all great ideas, but in practice also with their own set of downsides: how about those #!'s, and we have all certainly seen and written a few overly eager setTimeout's which quickly destroy the clients CPU and battery life.

In fact, because the browser VM is a shared resource, we have a classic tragedy of the commons: if every application plays nice, then everyone can have an optimal experience, but the incentives to do so are not clear. Problem is, until very recently we did not even have the tools to address this issue! Page Visibility API is the first HTML5 proposal that is trying to tackle this problem, and browser pre-rendering is also aiming to help us hide some of the network latency in our web applications - let's take a look under the hood.

Browser Pre-fetching vs. Pre-rendering

An average page render requires fetching a dozen resources alongside the actual HTML content. If you dig into your debug console, it is not uncommon to see pages which take on the order of ten seconds to load to completion. Thankfully, the browsers have implemented many tricks to make it seem as if the page is loading much faster - parallel downloads, highly optimized rendering engines, and a never ending battle to speed up Javascript execution. Nonetheless, usually this is still not enough to beat the "native experience".

Well, the server can help us as well: new protocols like SPDY are aiming to reduce the network overhead of fetching multiple resources, and there is even talk of enabling server push of related page assets. Think you can guess what the user may click on next? Firefox 3.5 enabled the pre-fetching API which allows us to hint to the browser what resources it may need to service a subsequent request:

<!--  Specify any & all resources to pre-fetch -->
<link rel="prefetch" href="/images/big.jpg">
 
<!-- or send an HTTP header -->
Link: </images/big.jpeg>; rel=prefetch
 

Pre-fetching is a simple optimization, but it requires that we explicitly specify each and every resource - just listing the link of the next HTML page is unlikely to result in a noticeable improvement in the user experience.

This is where the new pre-rendering proposal comes in: instead of specifying a single resource, what if the browser could fetch and render the entire next page, but hide it from you until you click on the link? As of about a month ago, pre-rendering support is in WebKit and Google is already prototyping it with "Instant Pages":

Pre-rendering wins and gotchas

At the moment, the pre-rendering API is limited: only one page can be pre-rendered across the entire VM, and only one page can be put into the pre-render queue per tab. Fetching an entire page taxes both the server and the client, hence you need be sure that you will actually need it. Google's web search team, for example, only enables pre-rendering on search results if they have very high confidence that you may actually click on the result.

Additionally, since we are now pre-rendering the entire page (HTML, CSS, and JS), how does this affect all the interactive content on the page? Knowing nothing about the pre-render step, the requested page can easily pin our CPU, register a pageview and make a request to an ad server for content that the user may never actually see! To solve this problem, WebKit developers have also added the Page Visibility API:

function handleVisibilityChange() {
  if (document.webkitHidden) {
    pausePageJavascript();
  } else {
    startPageJavascript();
  }
}
 
document.addEventListener("webkitvisibilitychange", handleVisibilityChange, false);
 

The webkitHidden property tells us the state of the page to solve the original visibility problem, but the webkitvisibilitychange event has another nice side effect: it allows the client to easily detect when a tab is visible, and when it is in the background. Why does this matter? Imagine you have an application which polls the client, or the server, every 50 milliseconds for some updates. With the visibility API, you can gracefully pause or degrade the timer to a much longer poll when the tab is in the background.

Minimizing latency on the web

Both pre-rendering and Page Visibility API's are still in development, but it is great to see more client-side tools to enable web developers to hide the underlying network latency. With these API's, instead of relying on an async Javascript stack, your next multi-step form can be rendered on the server and pre-rendered in a WebKit browser with instant feedback on the client!

Likewise, while browsers like Chrome are already downgrading background tabs in CPU priority, a client-side API to detect foreground tabs is a welcome addition. Let's hope that Firefox, Opera and IE jump on the bandwagon as well!


more »

RailsConf 2011 - Day 1 »

Created at: 16.05.2011 22:37, source: OnRails.org, tagged: Ruby on Rails html5 railsconf

RailsConf 2011 - Day 1 Today is the tutorial days.

Tutorial 1 : html5tutorial

I started RailsConf with the "Building Web Apps with HTML5: Beyond the Buzzword" by Mike Subelsky (@subelsky).
He prepared twelve html5 exercises that walked the about 250 attendees through various features of html5 over a 2.5 hour session. It's fun to have time to work on these features. The high point was having about 200 computers using Websockets to send data back and forth with his server. He created a small ruby program that used EventMachine::WebSocket and it was holding up quite well all these connections.
You can download his tutorial and all files from https://github.com/subelsky/html5tutorial. Look at the tutorial.html file for instructions.
Here are a few highlights of his talk:

1 - Feature Detection

By using the Modernizr library, we used modernizr-1.7.js, you can detect difference html5 of your browser.
For example:
  • Modernizr.canvas
  • Modernizr.websockets

2 - Basic Canvas Drawing

You can get a 2d context and draw on the canvas via that context. You can use fillRect and other primitives like moveTo and lineTo to draw.
    var canvas = document.getElementById("main");
    var context = canvas.getContext("2d");
    context.fillRect(0,0,20,20);

Here I just created a loop to generate 180 rectangles. Note they are clipped due to the width of the canvas.

3 - Canvas Image Manipulation

    var img = new Image();
    img.src = "http://www.flickr.com/photos/50183640@N05/5616041841/";
    img.onload = function() {
    context.drawImage(img,0,110);
    };


4 - Basic Animation

In this exercise we first load a new image then trap the keystroke and call the up method. Note we use jquery:
	var characters = new Image();
	characters.src = "http://onrails.org/files/20110516_characters.gif";

	characters.onload = function() {
	  $(window).keyup(move);
	};
In the move the x+y coordinates are updated accordingly and is cleared and redrawn.
	  context.clearRect(0,0,width,height);
	  context.drawImage(characters,33,0,32,32,x,y,32,32);	
Use the left and right arrow keys

5 - Fun With Forms

In this exercise we look at few attributes of the input tag like the placeholder and autofocus attributes.
	<input id="username" placeholder="Your name" autofocus>
	<input id="fn" placeholder="First name">
Use the slider below to scale the image:





We listen to the change event of the size input and call the draw() function. Note the last two of the drawImage below is the new width and height which will give us the scaling effect.
	<input id="size" type="range" min="4" max="320" step="8" value="60">
	function draw() {
	  context.clearRect(0,0,width,height);
	  context.drawImage(characters,33,0,32,32,0,0,sizeAmt,sizeAmt);
	}	

6 - Local Storage

If you are in Google Chrome press option-command-j to bring up the javascript console. The you can enter key-values pair associated with the page. It's like a client side cookie.
	localStorage.setItem('shaz','bot')
	localStorage.getItem('shaz')
	localStorage.length // return 1
	localStorage.clear()

7 - Canvas Cleanup

The canvas itself can be styled like any element. Here we set a black background:

  canvas { 
    background-color: black;
  }

  input { display: block; }	

8 - Web Sockets

That was the fun part of the presentation, mike created the a small ruby application and had over 200 clients connecting to it.
Here is an extract of the ruby program:
  class TutorialServer
    def run
      EventMachine.run do
        EventMachine::WebSocket.start(:host => @host, :port => @port) do |socket|
          socket.onmessage do |msg|
            @logger.info "received: #{msg}"
            broadcast(msg)
          end
        end
        EventMachine::add_periodic_timer(10) { broadcast(JSON.generate({ :type => "ping" })) }
      end
    end

    def broadcast(msg)
      @sockets.keys.each { |socket| socket.send(msg) }
    end
  end
  TutorialServer.new('0.0.0.0',8011).run
Then when the users moved the character image using the keyboard each keystroke was sent to his server.
// create the socket  
var ws = new WebSocket("ws://exp.subelsky.com:8011");

// sent to position+name to server
ws.send(JSON.stringify({ name: name, x: x, y: y, type: "move" }));
Ultimately he wanted to drive multiple clients from his server...but we ran out of time to dive into this.

And much more..

Mike covered additionally these topics: Embedded Media, Geolocation, Web Workers, Offline App

Well that was a couple of hours well spent! Go check out his material on github.

Tutorial 2 : Building Bulletproof Views

Now I'm at a great presentation from John Athayde & Bruce Williams on how to make elegant html, css and javascript. The slides will be posted online.
Here are some of the topics:
  • The Art of Template Writing
  • Nailing Navigation
  • Maintainable Forms
  • Don't Fear the Object
  • Going Mobile
  • packaging Assets
  • Questions & Discussion

And the day is not over...Ignite Rails tonight.
Enjoy!
Daniel Wanja


more »

Ruby & WebSockets: TCP for the Browser »

Created at: 22.12.2009 18:39, source: igvita.com, tagged: Architecture html5 realtime websocket

WebSockets are one of the most underappreciated innovations in HTML5. Unlike local storage, canvas, web workers, or even video playback, the benefits of the WebSocket API are not immediately apparent to the end user. In fact, over the course of the past decade we have invented a dozen technologies to solve the problem of asynchronous and bi-directional communication between the browser and the server: AJAX, Comet & HTTP Streaming, BOSH, ReverseHTTP, WebHooks & PubSubHubbub, and Flash sockets amongst many others. Having said that, it does not take much experience with any of the above to realize that each has a weak spot and none solve the fundamental problem: web-browsers of yesterday were not designed for bi-directional communication.

WebSockets in HTML5 change all of that as they were designed from the ground up to be data agnostic (binary or text) with support for full-duplex communication. WebSockets are TCP for the web-browser. Unlike BOSH or equivalents, they require only a single connection, which translates into much better resource utilization for both the server and the client. Likewise, WebSockets are proxy and firewall aware, can operate over SSL and leverage the HTTP channel to accomplish all of the above - your existing load balancers, proxies and routers will work just fine.

WebSockets in the Browser: Chrome, Firefox & Safari

The WebSocket API is still a draft, but the developers of our favorite browsers have already implemented much of the functionality. Chrome’s developer build (4.0.249.0) now officially supports the API and has it enabled by default. Webkit nightly builds also support WebSockets, and Firefox has an outstanding patch under review. In other words, while mainstream adoption is still on the horizon, as developers we can start thinking about much improved architectures that WebSockets enable. A minimal example with the help of jQuery:

> websocket.html

<html>
  <head>
    <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'></script>
    <script>
      $(document).ready(function(){
        function debug(str){ $("#debug").append("<p>"+str+"</p>"); };
 
        ws = new WebSocket("ws://yourservice.com/websocket");
        ws.onmessage = function(evt) { $("#msg").append("<p>"+evt.data+"</p>"); };
        ws.onclose = function() { debug("socket closed"); };
        ws.onopen = function() {
          debug("connected...");
          ws.send("hello server");
        };
      });
    </script>
  </head>
  <body>
    <div id="debug"></div>
    <div id="msg"></div>
  </body>
</html>
 

The above example showcases the bi-directional nature of WebSockets: send pushes data to the server, and onmessage callback is invoked anytime the server pushes data to the client. No need for long-polling, HTTP header overhead, or juggling multiple connections. In fact, you could even deploy the WebSocket API today without waiting for the browser adoption by using a Flash socket as an intermediate step: web-socket-js.

Streaming Data to WebSocket Clients

WebSockets are not the same as raw TCP sockets and for a good reason. While it may seem tempting to be able to open a raw TCP connections from within the browser, the security of the browser would be immediately compromised: any website could then access the network on behalf of the user, within the same security context as the user. For example, a website could open a connection to a remote SMTP server and start delivering spam - a scary thought. Instead, WebSockets extend the HTTP protocol by defining a special handshake in order for the browser to establish a connection. In other words, it is an opt-in protocol which requires a standalone server.

Nothing stops you from talking to an SMTP, AMQP, or any other server via the raw protocol, but you will have to introduce a WebSocket server in between to mediate the connection. Kaazing Gateway already provides adapters for STOMP and Apache ActiveMQ, and you could also implement your own JavaScript wrappers for others. And if a Java based WebSocket server is not for you, Ruby EventMachine also allows us to build a very simple event-driven WebSocket server in just a few lines of code:

> websocket.rb

require 'em-websocket'
 
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
  ws.onopen    { ws.send "Hello Client!"}
  ws.onmessage { |msg| ws.send "Pong: #{msg}" }
  ws.onclose   { puts "WebSocket closed" }
end
 

Consuming WebSocket Services

Support for WebSockets in Chrome and Safari also means that our mobile devices will soon support bi-directional push, which is both easier on the battery, and much more efficient for bandwidth consumption. However, WebSockets can also be utilized outside of the browser (ex: real-time data firehose), which means that a regular Ruby HTTP client should be able to handle WebSockets as well:

> em-http-websocket.rb

require 'eventmachine'
 
EventMachine.run {
  http = EventMachine::HttpRequest.new("ws://yourservice.com/websocket").get :timeout => 0
 
  http.errback { puts "oops" }
  http.callback {
    puts "WebSocket connected!"
    http.send("Hello client")
  }
 
  http.stream { |msg|
    puts "Recieved: #{msg}"
    http.send "Pong: #{msg}"
  }
}
 

WebSocket support is still an experimental branch within em-http-request, but the aim is to provide a consistent and fully transparent API: simply specify a WebSocket resource and it will do the rest, just as if you were using a streaming HTTP connection! Best of all, HTTP & OAuth authentication, proxies and existing load balancers will all work and play nicely with this new delivery model.

WebHooks, PubSubHubbub, WebSockets, ...

Of course, WebSockets are not the panacea to every problem. WebHooks and PubSubHubbub are great protocols for intermittent push updates where a long-lived TCP connection may prove to be inefficient. Likewise, if you require non-trivial routing then AMQP is a powerful tool, and there is little reason to reinvent the powerful presence model built into XMPP. Right tool for the right job, but WebSockets are without a doubt a much-needed addition to every developers toolkit.


more »