AJAX Long-Pull (almost HTTP Push)

Created 2006-10-20 / Edited 2006-11-19

Tags: Perl, Continuity, AJAX, HTTP Push, Code

I've been doing some fun things with Continuity in conjunction with scott to prepare for Desert Code Camp. The latest is combining XmlHttpRequest with Continuity in a new way, simulating HTTP Push.

It's really easy, actually. I put together a chat application which you can see in the Continuity Examples Directory. When you first go to the page, it immediately sends a background GET request back to the server, which actually opens a second session. That session then blocks, waiting for a variable to change to indicate that there are new messages.

So I have this code which watches for new chat messages:

sub pushstream {
  my ($req) = @_;
  while(1) {
    print STDERR "**** Waiting for message ****\n";
    my $w = Coro::Event->var(var => \$got_message, poll => 'w');
    $w->next->cancel; # Block, waiting for an update
    print STDERR "**** GOT MESSAGE, SENDING ****\n";
    my $log = join "<br>", @messages;
    $req->print($log);
    $req->next; # Once the client is ready, they'll ask for more
  }       
}       

Then, when the mainloop gets a new message, it just sets $got_message = 1 and all the watchers are triggered, giving all the clients the new message.

For fun, I opened up four webbrowsers (FF, IE6, Opera, and Konqueror) and recorded a chat between all four -- Four Browser AJAX Long-Pull (fake Push) Demo.

This is not really very robust -- but it should only take a few properly placed timeouts to fix that. I hear proxies can wreak havoc on this method too, so keep that in mind.