Skip to content

Instantly share code, notes, and snippets.

@Cside
Created April 2, 2011 05:23
Show Gist options
  • Save Cside/899250 to your computer and use it in GitHub Desktop.
Save Cside/899250 to your computer and use it in GitHub Desktop.
websocket_test.pl
#!perl
use strict;
use warnings;
use Plack::Builder;
use Plack::Request;
use Plack::Middleware::WebSocket;
use AnyEvent;
use AnyEvent::Handle;
use Coro;
use Coro::LWP;
use Furl;
my $furl = Furl->new;
my @coros;
my @urls = (
'http://b.hatena.ne.jp/',
'http://c.hatena.ne.jp/',
'http://a.hatena.ne.jp/',
'http://h.hatena.ne.jp/',
'http://ugomemo.hatena.ne.jp/',
);
my $DATA = do { local $/; scalar <DATA> };
my $app = sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $res = $req->new_response(200);
if (not $env->{'psgi.streaming'}) {
die 'this handler does not support psgi.streaming';
}
if ($req->path eq '/') {
my $data = $DATA;
$data =~ s/{{{HOST}}}/$env->{HTTP_HOST}/g;
$res->content_type('text/html; charset=utf-8');
$res->content($data);
}
elsif ($req->path eq '/req') {
if (my $fh = $env->{'websocket.impl'}->handshake) {
my $handle = AnyEvent::Handle->new(fh => $fh);
return sub {
my $respond = shift;
on_read $handle sub {
shift->push_read(
'AnyEvent::Handle::Message::WebSocket',
sub {
my $msg = $_[1];
if ($msg eq 'fire-event') {
concurrent_get($handle);
}
},
);
};
on_error $handle sub {
warn "error: $_[2]";
$respond->([
500, [ 'Content-Type', 'text/plain' ], [ "error: $_[2]" ],
]);
};
};
}
$res->code($env->{'websocket.impl'}->error_code);
}
else {
$res->code(404);
}
return $res->finalize;
};
sub concurrent_get {
my $handle = shift;
my $count = 0;
my $push_write = sub {
my $msg = shift;
$handle->push_write(
'AnyEvent::Handle::Message::WebSocket',
$msg,
);
};
for (1 .. scalar(@urls)) {
my $i = $_;
my $url = $urls[$i - 1];
push @coros, async {
my $res = $furl->get($url);
$push_write->("[$i]$url: ".$res->status_line);
$count++;
if ($count == scalar(@urls)) {
$push_write->("all requests finished");
}
};
}
}
builder {
enable 'WebSocket';
$app;
};
__DATA__
<!DOCTYPE html>
<html>
<head>
<title>Plack::Middleware::WebSocket</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<style type="text/css">
#log {
border: 1px solid #DDD;
padding: 0.5em;
}
</style>
</head>
<body>
<script type="text/javascript">
function log (msg) {
$('#log').text($('#log').text() + msg + "\n");
}
$(function () {
var ws = new WebSocket('ws://{{{HOST}}}/req');
log('WebSocket start');
ws.onopen = function () {
log('connected');
};
ws.onmessage = function (ev) {
log('received: ' + ev.data);
};
ws.onerror = function (ev) {
log('error: ' + ev.data);
}
ws.onclose = function (ev) {
log('closed');
}
$('#button').click(function() {
var data = 'fire-event';
ws.send(data);
log('sent concurrent request');
return false;
});
});
</script>
<button id="button">
Start Concurrent Request
</button>
<pre id="log"></pre>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment