uwMike.com

I am engaged to the beautiful and wonderful Tara Cleaver!

Pushing Data to the Browser With Open-Get

January 22nd, 2008 6

For anyone who’s curious how Gmail’s chat widget notifies your browser that a new message has arrived, be curious no longer: here’s a simplified page that [demonstrates the method used](http://sandbox.mikepurvis.com/js/openget/).

Note: Before we go on, I should just clarify that nothing here is based on insider knowledge of Google (I was never anywhere near the Gmail code), and any opinions expressed are mine alone.

This demo itself is of interest to technical folks, because it demonstrates a way for programmers to work around another frustrating limitation that arises from the architecture of the web—that when an interaction over http takes place between a client (browser) and a server (website), the client must always be the one initiating the connection.

Update: In the comments, Rob has pointed out that this technique is part of an umbrella term “[Comet](http://cometdaily.com/),” which generally describes techniques for pushing data to the browser. [Simon Willison has more](http://simonwillison.net/2007/Dec/5/comet/).

The first way this problem was dealt with was by polling, at first using a meta-tag or JavaScript to trigger periodic reloads of the page in question—a lot of older webmail clients did this, to refresh the inbox. As Ajax started to pick up a few years ago, polling was done with an asynchronous fetch. This is what most modern webmail clients do, and the principle works also works well when you want snapshots of continuous data, such as that pertaining to financial markets.

But how does Gmail—and this demo—get almost instant notification? To achieve that responsiveness with polling has serious scaling issues. (Remember, even if a polling request basically returns nothing, there’s an overhead that accumulates from re-sending the headers on each poll. You can get a sense of this cost using a tool like [LiveHTTPHeaders](http://livehttpheaders.mozdev.org/).)

The strategy, in a nutshell, is that the request for new messages is made immediately, and the server simply holds the connection open and doesn’t answer *until it has something to say*. But before moving on to that, a diversion.

### Story Time

I finally implemented the little chat demo in a couple hours over the weekend. But the idea of *how* to do it first occurred to me almost exactly three years ago, before I had had much exposure to “serious” JavaScript.

Settlers

I was working at my very first co-op job, and was discussing with a colleague about how to implement a [Settlers of Catan game in only HTML and JavaScript](http://sandbox.mikepurvis.com/css/settlers/), without depending on plugins like Flash or Java. The term “Ajax” hadn’t yet appeared (that would come on [February 18th](http://www.adaptivepath.com/ideas/essays/archives/000385.php)), but we knew from Gmail that it was possible to do asynchronous JS, and that seemed all that was really necessary to make Settlers work.

Except for one thing. What if a player wants to trade with you? The server needs a way of notifying the player that they have a pending trade offer. Polling on a 1- or 2-second period would have been adequate for that, but as I slept on it, it occurred to me that it should be possible to simulate a “push” just by having the server sit on the open connection until it had data to send.

As it turned out, we lost interest in the project, and I never pursued the idea for pushing data to the browser. Later, I would also realise that trying to use the browser’s scrollbars was foolish; when Google Maps launched, it became obvious that grab-and-drag was the right model for navigating a 2-D space in the browser.

When Gmail launched chat, I think I just assumed there was a hidden flash movie or something that made the magic happen.

That is, until just last week, now at RIM, when I was chatting with a colleague about how the BlackBerry receives push email. Now, obviously, the phone network is set up so that each device can receive push data—the phone ringing is a “pushed” event. But the BlackBerry is special among mobile phones in that it also receives *email* pushed. When other phones do email (until recently, anyways), they have to poll a server to check for messages… polling that costs battery life and network traffic.

We started discussing push to browsers, and someone mentioned about the new version of Gmail using a dangling GET connection to receive chat messages, and there it was. I don’t know if the older version did it this way or with polling, but as far as I can tell with Firebug, Gmail receives all server notifications (chat events and new emails, basically) through the same open-get stream.

And, of course, Google Docs (formerly Writely) uses the same trick to receive changes to a document as multiple authors collaborate on it.

### How It Actually Works

Open Connection

The client-side JavaScript issues a GET request on the polling URL, and the server doesn’t return anything… it just stalls, waiting. A typical request has thirty seconds to return data before closing in a timeout. However, there are several ways to extend this limitation. On the server, PHP’s ini_set lets one extend the [max_execution_time](http://ca3.php.net/manual/en/ref.info.php#ini.max-execution-time). Within JavaScript, you’re more at the mercy of the browser, but if you slowly trickle dummy content (say, a single character every twenty seconds) you can stop the browser from closing the connection on you.

As with many paradigm shifts, this one exposes an interesting limitation in the existing tools—in this case, PHP. The only way for one request in PHP to communicate with another is through a shared common resource such as a file or the database connection. In my case, I used a file, called messages.csv. This is horribly bad, since you end up with legions of get.php requests all polling that file waiting for changes. Obviously bad and unscalable, but good enough for a proof of concept. A production implementation of this would need to run on server software capable of passing messages between requests.

JS guru Douglas Crockford calls this concept “duplexing” in a 2006 proposal for a [JSONRequest browser service](http://www.json.org/JSONRequest.html). So the idea is out there in the public space… at this point I’m just curious to see where else it can go. Ultimately, it’s applications that need the instant notification, but also require aspects of normal browser behaviour that Flash is unable to provide. Google has nailed the top two with a mail client and collaborative document editor, but I can’t help thinking that there’s at least a few other neat products that could be built around this kind of notification system.

Mike

p.s.
For the curious, [here's the JavaScript behind the demo](http://sandbox.mikepurvis.com/js/openget/chat.js), powered by [jQuery](http://jquery.com/).

You can find in Google french chaussland shop without problems. | Unical Driving School Reviews | Agen Bola Terpercaya

Discussion

  1. Wonderful Mike. In hindsight this makes perfect sense, thanks. To quote Terill, “this is genius”.

    Is there any work arounds that the client can perform doesn’t want to play by your rules (i.e. does not leave the connection open for you)? I am going to assume the answer is a no but it would be nice if there was something.

    Posted at 12:06 am on January 23rd by Scott.

  2. Functionality like this has existed for a little while in a few js toolkits. An attempt has been made to coalesce knowledge around the name ‘comet’, but it doesn’t really seem to be catching on.

    http://alex.dojotoolkit.org/?p=545

    Posted at 5:59 am on January 23rd by Rob Drimmie.

  3. Interesting, thanks Rob. It’s a bit tough to search for something like this, when you don’t know the name to use. I’d be interested for any more information on people’s experiences, especially dealing with IE. As far as I can tell, Gmail uses an ActiveX component to patch some aspect of IE6 to make this work, but I haven’t had a chance to really figure out what the issue is. (My main machine is a Mac, so I debugging on IE is always kind of an event.)

    Posted at 8:12 am on January 23rd by Mike Purvis.

  4. [...] via uwMike » Archive » Pushing Data to the Browser With Open-Get. [...]

    Posted at 11:31 pm on July 7th by RSully» Blog Archive » [Follow up] Ajax Push – “Pushing Data to the Browser With Open-Get”.

  5. Your demo is broke btw

    Posted at 6:23 pm on September 18th by RSully.

  6. Your DEMO is not working… Can someone look at it. I would really like to examine it.
    I tried Firefox 3 and Safari 4 browsers..

    Posted at 3:43 pm on October 26th by Primoz.

© 2004-2014, Mike Purvis, some rights reserved. I'm running Wordpress, and I have an RSS feed.

resume writing services