Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
AnyMQ, Hippie
 and the real-time web

       YAPC::Asia 2010 Tokyo
   Chia-liang Kao clkao@clkao.org
clkao
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie:Pipe
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie::Pipe
Plack: Web
PSGI
$env




[
       '200',
       [ 'Content-Type' => 'text/plain' ],
       [ "Hello World" ],
]
$env->{PATH_INFO}


$env




[
       '200',
       [ 'Content-Type' => 'text/plain' ],
       [ "Hello World" ],
]
$env->{PATH_INFO}

       Plack::Request->new($env)->path_info
$env




[
       '200',
       [ 'Content-Type' => 'text/p...
$env
                 Streaming Interface
sub {
   my $responder = shift;
   my $writer = $responder->([
          '200',
...
$env
       Streaming Interface(Cont.)
sub {
   my $responder = shift;
   my $writer = $responder->([
           '200',
  ...
CGI.pm

! ☠! ☠! ☠
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie::Pipe
AnyEvent
•
•
AnyEvent
•
•
    use AnyEvent::HTTP;

    http_get "http://yapc.asia/",
                  sub { print $_[1] };
    # do so...
POE
sub POE::Kernel::ASSERT_DEFAULT () { 1 }

use HTTP::Request;
use POE qw(Component::Client::HTTP);

POE::Component::Client:...
☹
use AnyEvent::HTTP;

http_get "http://yapc.asia/",
              sub { print $_[1] };




      ☺
AnyEvent::*
  AnyEvent-AIO AnyEvent-APNS AnyEvent-Atom-Stream AnyEvent-BDB AnyEvent-
  Beanstalk AnyEvent-Connection AnyEv...
AnyMQ
AnyMQ
• Tatsumaki::MessageQueue
AnyMQ
• Tatsumaki::MessageQueue
AnyMQ
• Tatsumaki::MessageQueue
AnyMQ
• Tatsumaki::MessageQueue
•
AnyMQ
• Tatsumaki::MessageQueue
•

• Moose
AnyMQ
• Tatsumaki::MessageQueue
•

• Moose
AnyMQ
• Tatsumaki::MessageQueue
•

• Moose
AnyMQ

my $bus = AnyMQ->new;
my $topic = $bus->topic("Foo");

my $sub = $bus->new_listener($topic);
$sub->poll(sub { my $m...
AnyMQ with AMQP
my $bus = AnyMQ->new_with_traits
          ( traits => [ ‘AMQP’],
            # host => ..., port => ..);
...
AnyMQ with AMQP
AnyMQ with AMQP
my $bus = AnyMQ->new_with_traits           my $bus = AnyMQ->new_with_traits
          ( traits => [ ‘AMQP’...
AnyMQ with AMQP
my $bus = AnyMQ->new_with_traits                  my $bus = AnyMQ->new_with_traits
          ( traits => [...
!
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie::Pipe
Comet


-
Comet
The word comet came to English by way of the Latin word cometes. This word, in turn, came
from the Greek word κόμη, ...
Comet
The word comet came to English by way of the Latin word cometes. This word, in turn, came
from the Greek word κόμη, ...
• gmail
• twitter
• facebook updates
!

•               XHR

•      iframe

• FF   IE

•
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie::Pipe
HTML5 Standard
ws://example.com

wss://example.com
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
my @keys = map {
    my $k = $env>{'HTTP_SEC_WEBSOCKET_KEY'.$_};
    join('', $k =~ m/d/g) / scalar @{[$k =~ m/ /g]};
} (1...
Messages surrounded
by x{00} and x{ff}
Websockets API
Websockets API

ws = new WebSocket("ws://foo.com:5000”));

ws.onopen = function(ev) { ... }
ws.onmessage = function(ev) { ...
Websockets API

    ws = new WebSocket("ws://foo.com:5000”));

    ws.onopen = function(ev) { ... }
    ws.onmessage = fun...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
Request:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Prot...
• PSGI, Plack
• AnyEvent, AnyMQ, AMQP
• Server-push, comet
• Websocket
• Web::Hippie, Web::Hippie::Pipe
Web
•   : Websocket, MXHR
•                       : Websocket, MXHR

    enable "+Web::Hippie";
    sub { my $env    = shift;
          my $args   =...
•                       : Websocket, MXHR
                          Just a normal PSGI-app!
    enable "+Web::Hippie";
   ...
•                       : Websocket, MXHR
                          mount it to /_hippie
    enable "+Web::Hippie";
    su...
Must use PSGI servers supporting
    psgi.nonblocking:
Must use PSGI servers supporting
    psgi.nonblocking:


       twiggy
       feersum
Websocket
 mxhr     ?
?
…
Hippie::Pipe


     +
Hippie::Pipe
•                         :
    Websocket MXHR poll   AnyMQ support
Hippie::Pipe
•                          :
    Websocket MXHR poll   AnyMQ support
enable "+Web::Hippie";
enable "+Web::Hip...
Hippie::Pipe(Cont.)
Hippie::Pipe(Cont.)
my $topic = $bus->topic(‘news’);
# my $sub = $env->{'hippie.listener'};
if ($env->{PATH_INFO} eq ‘/new...
Hippie::Pipe(Cont.)
my $topic = $bus->topic(‘news’);
# my $sub = $env->{'hippie.listener'};
if ($env->{PATH_INFO} eq ‘/new...
Hippie::Pipe(Cont.)
my $topic = $bus->topic(‘news’);
# my $sub = $env->{'hippie.listener'};
if ($env->{PATH_INFO} eq ‘/new...
hpipe = new Hippie.Pipe();
$(hpipe)
    .bind(“ready”, function() {
         hpipe.send({type:    ‘news.viewer’,
         ...
hpipe = new Hippie.Pipe();
$(hpipe)
    .bind(“ready”, function() {
         hpipe.send({type:    ‘news.viewer’,
         ...
hpipe = new Hippie.Pipe();
$(hpipe)
    .bind(“ready”, function() {
         hpipe.send
         hpipe.send({type:    ‘new...
hpipe = new Hippie.Pipe();
$(hpipe)
    .bind(“ready”, function() {
         hpipe.send
         hpipe.send({type:    ‘new...
Hippie::Pipe(Cont.)
Hippie::Pipe(Cont.)
# my $sub = $env->{'hippie.listener'};
# my $msg = $env->{'hippie.message'};

if ($env->{PATH_INFO} eq...
Hippie::Pipe(Cont.)
# my $sub = $env->{'hippie.listener'};
# my $msg = $env->{'hippie.message'};

if ($env->{PATH_INFO} eq...
Hippie::Pipe(Cont.)
# my $sub = $env->{'hippie.listener'};
# my $msg = $env->{'hippie.message'};

if ($env->{PATH_INFO} eq...
DEMO
at Jesse’s Talk 12:00
        today
DEMO
Thank you!
special thanks to Ishigaki-san and
   Danjou-san for translations
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
Upcoming SlideShare
Loading in …5
×

AnyMQ, Hippie, and the real-time web

5,161 views

Published on

Published in: Business, Technology
  • Be the first to comment

AnyMQ, Hippie, and the real-time web

  1. 1. AnyMQ, Hippie and the real-time web YAPC::Asia 2010 Tokyo Chia-liang Kao clkao@clkao.org
  2. 2. clkao
  3. 3. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie:Pipe
  4. 4. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  5. 5. Plack: Web
  6. 6. PSGI
  7. 7. $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  8. 8. $env->{PATH_INFO} $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  9. 9. $env->{PATH_INFO} Plack::Request->new($env)->path_info $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  10. 10. $env Streaming Interface sub { my $responder = shift; my $writer = $responder->([ '200', [ 'Content-Type' => 'text/plain' ]); # later, of in a callback $writer->write(“Hello world!”); $writer->close(); }
  11. 11. $env Streaming Interface(Cont.) sub { my $responder = shift; my $writer = $responder->([ '200', [ 'Content-Type' => 'text/plain' ]); # later, of in a callback my $w; $w = AnyEvent->timer(after => 3, cb => sub { $writer->write(“Hello world!”); $writer->close(); }); }
  12. 12. CGI.pm ! ☠! ☠! ☠
  13. 13. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  14. 14. AnyEvent • •
  15. 15. AnyEvent • • use AnyEvent::HTTP; http_get "http://yapc.asia/", sub { print $_[1] }; # do something else
  16. 16. POE
  17. 17. sub POE::Kernel::ASSERT_DEFAULT () { 1 } use HTTP::Request; use POE qw(Component::Client::HTTP); POE::Component::Client::HTTP->spawn(   Alias => 'ua', # defaults to 'weeble'   Timeout => 20, # defaults to 180 seconds ); POE::Session->create(   inline_states => {     _start => sub {       POE::Kernel->post(         'ua', # posts to the 'ua' alias         'request', # posts to ua's 'request' state         'response', # which of our states will receive the response         HTTP::Request->new(GET => “http://osdc.tw”),       );     },     _stop => sub {},     response => &response_handler,   }, ); POE::Kernel->run(); exit; sub response_handler {   my ($request_packet, $response_packet) = @_[ARG0, ARG1];   my $request_object = $request_packet->[0];   my $response_object = $response_packet->[0]; }
  18. 18.
  19. 19. use AnyEvent::HTTP; http_get "http://yapc.asia/", sub { print $_[1] }; ☺
  20. 20. AnyEvent::* AnyEvent-AIO AnyEvent-APNS AnyEvent-Atom-Stream AnyEvent-BDB AnyEvent- Beanstalk AnyEvent-Connection AnyEvent-CouchDB AnyEvent-DBI AnyEvent-DBI- Abstract AnyEvent-EditText AnyEvent-FCGI AnyEvent-FCP AnyEvent-FIFO AnyEvent- FastPing AnyEvent-Feed AnyEvent-Filesys-Notify AnyEvent-FriendFeed-Realtime AnyEvent-GPSD AnyEvent-Gearman AnyEvent-Gearman AnyEvent-Gmail-Feed AnyEvent-HTTP AnyEvent-HTTP-MXHR AnyEvent-HTTPD AnyEvent-I3 AnyEvent-IRC AnyEvent-JSONRPC-Lite AnyEvent-Kanye AnyEvent-MP AnyEvent-MPRPC AnyEvent- Memcached AnyEvent-Mojo AnyEvent-Monitor-CPU AnyEvent-Pcap AnyEvent-Plurk AnyEvent-Postfix-Logs AnyEvent-RTPG AnyEvent-Redis AnyEvent-RetryTimer AnyEvent-ReverseHTTP AnyEvent-Riak AnyEvent-Run AnyEvent-SCGI AnyEvent-SMTP AnyEvent-SNMP AnyEvent-Subprocess AnyEvent-Superfeedr AnyEvent-Twitter AnyEvent-Twitter-Stream AnyEvent-Watchdog AnyEvent-Worker AnyEvent-XMLRPC AnyEvent-XMPP AnyEvent-mDNS
  21. 21. AnyMQ
  22. 22. AnyMQ • Tatsumaki::MessageQueue
  23. 23. AnyMQ • Tatsumaki::MessageQueue
  24. 24. AnyMQ • Tatsumaki::MessageQueue
  25. 25. AnyMQ • Tatsumaki::MessageQueue •
  26. 26. AnyMQ • Tatsumaki::MessageQueue • • Moose
  27. 27. AnyMQ • Tatsumaki::MessageQueue • • Moose
  28. 28. AnyMQ • Tatsumaki::MessageQueue • • Moose
  29. 29. AnyMQ my $bus = AnyMQ->new; my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $topic->publish($msg)
  30. 30. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $topic->publish($msg)
  31. 31. AnyMQ with AMQP
  32. 32. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg) my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg)
  33. 33. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg) AMQP Server my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg)
  34. 34. !
  35. 35. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  36. 36. Comet -
  37. 37. Comet The word comet came to English by way of the Latin word cometes. This word, in turn, came from the Greek word κόμη, which means "hair of the head". The Greek scientist and philosopher Aristotlefirst used the derived form of κόμη, κομήτης, to describe what he saw as "stars with hair." Theastronomical symbol for comets is (☄), consisting of a small disc with three hairlike extensions. -
  38. 38. Comet The word comet came to English by way of the Latin word cometes. This word, in turn, came from the Greek word κόμη, which means "hair of the head". The Greek scientist and philosopher Aristotlefirst used the derived form of κόμη, κομήτης, to describe what he saw as "stars with hair." Theastronomical symbol for comets is (☄), consisting of a small disc with three hairlike extensions. - • 2006 •
  39. 39. • gmail • twitter • facebook updates
  40. 40. ! • XHR • iframe • FF IE •
  41. 41. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  42. 42. HTML5 Standard
  43. 43. ws://example.com wss://example.com
  44. 44. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  45. 45. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  46. 46. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  47. 47. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  48. 48. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  49. 49. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  50. 50. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  51. 51. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  52. 52. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com New in draft#76 ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  53. 53. my @keys = map { my $k = $env>{'HTTP_SEC_WEBSOCKET_KEY'.$_}; join('', $k =~ m/d/g) / scalar @{[$k =~ m/ /g]}; } (1,2); md5(pack('NN', @keys) . $key3);
  54. 54. Messages surrounded by x{00} and x{ff}
  55. 55. Websockets API
  56. 56. Websockets API ws = new WebSocket("ws://foo.com:5000”)); ws.onopen = function(ev) { ... } ws.onmessage = function(ev) { ... } ws.onclose = function(ev) { ... } ws.onerror = function(ev) { ... } ws.send(....);
  57. 57. Websockets API ws = new WebSocket("ws://foo.com:5000”)); ws.onopen = function(ev) { ... } ws.onmessage = function(ev) { ... } ws.onclose = function(ev) { ... } ws.onerror = function(ev) { ... } ws.send(....); Can accept cross-site connection with Origin and Sec- WebSocket-Origin headers
  58. 58. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  59. 59. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  60. 60. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  61. 61. Web
  62. 62. • : Websocket, MXHR
  63. 63. • : Websocket, MXHR enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  64. 64. • : Websocket, MXHR Just a normal PSGI-app! enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  65. 65. • : Websocket, MXHR mount it to /_hippie enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  66. 66. Must use PSGI servers supporting psgi.nonblocking:
  67. 67. Must use PSGI servers supporting psgi.nonblocking: twiggy feersum
  68. 68. Websocket mxhr ?
  69. 69. ?
  70. 70.
  71. 71. Hippie::Pipe +
  72. 72. Hippie::Pipe • : Websocket MXHR poll AnyMQ support
  73. 73. Hippie::Pipe • : Websocket MXHR poll AnyMQ support enable "+Web::Hippie"; enable "+Web::Hippie::Pipe", bus => AnyMQ->new; sub { my $env = shift; my $sub = $env->{'hippie.listener'}; my $bus = $env->{'hippie.bus'}; my $msg = $env->{'hippie.message'}; # Your handler based on PATH_INFO: # /new_listener, /error, /message }
  74. 74. Hippie::Pipe(Cont.)
  75. 75. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  76. 76. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  77. 77. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  78. 78. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  79. 79. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  80. 80. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  81. 81. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  82. 82. Hippie::Pipe(Cont.)
  83. 83. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } }
  84. 84. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } }
  85. 85. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } } # Client: # bind(“message.news.viewer”, function(){..})
  86. 86. DEMO at Jesse’s Talk 12:00 today
  87. 87. DEMO
  88. 88. Thank you! special thanks to Ishigaki-san and Danjou-san for translations

×