Smart Clients: ReverseHTTP & WebSockets

Polling architectures, as pervasive as they are today, did not come about due to their efficiency. Whether you are maintaining a popular endpoint (Twitter), or trying to get near real-time news (RSS), neither side benefits from this architecture. Over the years we’ve built a number of crutches in the form of Cache headers, ETags, accelerators, but none have fundamentally solved the problem - because the client remains ‘dumb’ the burden is still always on the server. For that reason, it’s worth paying attention to some of the technologies which are seeking to reverse this trend: ReverseHTTP & WebSockets.

Smart(er) Clients: Pushing Complexity to the Edges

Our web-browsers today are, for the most part, passive consumers. This model has worked wonderfully up until now, but as thought experiment, think about the implications on your architecture if the browsers were smarter. For example, what if the browser also contained a web server? For one, this would mean that the browser and the web-server would be peers: they could talk via HTTP, use OAuth, Webhooks, etc!

Brushing NAT and firewall complications aside for a few seconds, this would mean that any browser could register itself via a webhook, and the server would simply propagate the updates to each client whenever new data is available (aka, PubSubHubbub with the client). Fast and efficient.

So how do you go about running a web-server in your browser? It is possible in theory, but the support is lacking. Firefox has a built in Javascript webserver for testing, but it requires XPCOM privileges; there is some talk on the Jetpack mailing lists about supporting this feature, but nothing conclusive; node.js is an evented V8 powered web-server, but it can’t run within Chrome. The closest you will get without modify the core of your browser is Firefox POW (Plain Old Webserver) extension, but we need something much more flexible.

Hybrid Clients: ReverseHTTP & Supernodes

The first time you read the proposed ReverseHTTP, or equivalent spec, it will undoubtedly feel like a crazy idea. Having said that, it works. Because most clients are hidden behind personal / corporate firewalls or NAT’s, it renders them unreachable for a raw client-side HTTP push model. ReverseHTTP proposes a hybrid solution: another web-server in middle acts a proxy, and the client maintains a persistent connection to it. Whenever a request comes to the proxy, it is relayed to the client via the persistent connection, where the response is determined by the browser and finally relayed back to the originating source. In effect, you are running a webserver in your browser. Give it a try, and if you’re curious, check out the server code as well.

Unfortunately, this is still a half-hearted solution because it introduces yet another layer of infrastructure into the equation, but it also has its benefits. First, the scalability complexity is propagated down to the edges – a client, a hosting provider, or even an ISP can maintain such proxy nodes for their users. In fact, that is exactly what Opera Unite is all about. Blur your eyes to cut through the marketing, and you’ll see that, in fact, the “revolution” is the ability for a browser to act as a server, via the Opera Unite proxy service. Sounds crazy?

Microsoft’s Teredo service (tunneling IPv6 traffic over IPv4) has been providing this very service for free for several years now to all Windows users. Last but not least, this is also the same principle that powers your favorite P2P client (Skype, Kazaa, etc). It is not as crazy as it seems.

Bi-directional Communication With WebSockets API

Of course, we also can’t forget Comet, BOSH, or many other attempts at the same problem. Personally, I’ve been holding off for a simpler solution. All I want is a socket – Flash has it, why can’t the web browser too? Thankfully, HTML 5 has an answer: WebSocket API.

// open a websocket var conn = new WebSocket ( "ws://yourwebservice.com/service" ); // act on incoming data conn . onopen = function ( e ) { ... } conn . onread = function ( e ) { ... } conn . onclose = function ( e ) { ... } // push messages back to server conn . send ( "Bi-directional!" );

As more and more browsers start adopting HTML 5 features I’m hoping to see WebSockets become a reality within the next couple of years. Full bi-directional data exchange between the client and server, without a need for a third party in between – that is what Opera Unite announcement should have been. It still means maintaining persistent connections between client and server, which is arguably not as elegant as registering your browser session through a webhook, but there is a need for both solutions. One is great for intermittent updates, the other (WebSockets) are the right answer for high-velocity streams.