package Amon2::Plugin::Web::WebSocket; use strict; use warnings; use utf8; use Amon2::Util; use AnyEvent::Handle; use Amon2::Web::WebSocket; use Amon2::Web::Response::Callback; use Protocol::WebSocket 0.00906; use Protocol::WebSocket::Frame; use Protocol::WebSocket::Handshake::Server; sub init { my ($class, $c, $conf) = @_; Amon2::Util::add_method(ref $c || $c, 'websocket', \&_websocket); } sub _websocket { my ($c, $code) = @_; my $fh = $c->req->env->{'psgix.io'} or return $c->create_response( 500, [], [] ); my $ws = Amon2::Web::WebSocket->new(); my $hs = Protocol::WebSocket::Handshake::Server->new_from_psgi( $c->req->env ); $hs->parse($fh) or return $c->create_response( 400, [], [ $hs->error ] ); $code->( $ws ); my $res = Amon2::Web::Response::Callback->new( code => sub { my $respond = shift; eval { my $h = AnyEvent::Handle->new( fh => $fh ); $ws->{send_message} = sub { my $message = shift; $message = Protocol::WebSocket::Frame->new($message) ->to_bytes; $h->push_write($message); }; my $frame = Protocol::WebSocket::Frame->new(); $h->push_write( $hs->to_string ); $h->on_read( sub { $frame->append( $_[0]->rbuf ); while ( my $message = $frame->next ) { $ws->call_receive_message( $c, $message ); } } ); $h->on_error( sub { $ws->call_error(); } ); $h->on_eof( sub { $ws->call_eof(); } ); }; if ($@) { warn $@; die "Cannot process websocket"; } }, ); return $res; } 1; __END__ =head1 NAME Amon2::Plugin::Web::WebSocket - [EXPERIMENTAL]websocket plugin for Amon2 =head1 SYNOPSIS any '/echo' => sub { my ($c) = @_; return $c->websocket(sub { my $ws = shift; $ws->on_receive_message(sub { my ($c, $message) = @_; $ws->send_message("YAY: " . $message); }); }); }; =head1 DESCRIPTION This plugin provides websocket feature for Amon2. You can use websocket very easily with Amon2. =head1 METHODS =over 4 =item $c->websocket(\&callback); =back