=head1 NAME
PEF::Front::WebSocket - WebSocket framework for PEF::Front
=head1 SYNOPSIS
# startup.pl
use PEF::Front::Websocket;
# usual startup stuff...
# $PROJECT_DIR/app/WSTest/WebSocket/Echo.pm
package WSTest::WebSocket::Echo;
sub on_message {
my ($self, $message) = @_;
$self->send($message);
}
1;
=head1 DESCRIPTION
This module makes WebSockets really easy. Every kind of WebSocket
is in its own module. Default routing scheme is C</ws$WebSocketClass>.
WebSocket handlers are located in C<$PROJECT_DIR/app/$MyAPP/WebSocket>.
=head2 Prerequisites
This module requires L<Coro>, L<AnyEvent> and L<PSGI> server that must
meet the following requirements.
=over
=item *
C<psgi.streaming> environment is true.
=item *
C<psgi.nonblocking> environment is true.
=item *
C<psgix.io> environment holds a valid raw IO socket object. See L<PSGI::Extensions>.
=back
L<uwsgi|
https://uwsgi-docs.readthedocs.io/en/latest/PSGIquickstart.html>
version 2.0.14+ meets all of them with C<psgi-enable-psgix-io = true>.
=head1 WEBSOCKET INTERFACE METHODS
=head2 on_message($message, $type)
A subroutine that is called on new message from client.
=head2 on_drain()
A subroutine that is called when there's nothing to send to
client after some successful send.
=head2 on_open()
A subroutine that is called each time it establishes a new
WebSocket connection to a client.
=head2 on_error($message)
A subroutine that is called when some error
happens while processing a request.
=head2 on_close()
A subroutine that is called on WebSocket close event.
=head2 no_compression()
When defined and true then no compression will be used even when it
supported by browser and server.
=head1 INHERITED METHODS
Every WebSocket class is derived from C<PEF::Front::Websocket::Base>
which is derived from C<PEF::Front::Websocket::Interface>. Even when you don't
derive your class from C<PEF::Front::Websocket::Base> explicitly,
this class will be added automatically to hierarchy.
=head2 send($buffer[, $type])
Sends $buffer to client. By default $type is 'text'.
=head2 close()
Closes WebSocket.
=head2 is_defunct()
Returns true when socket is closed or there's some error on it.
=head1 CONFIGURATION
=over
=item cfg_websocket_heartbeat_interval
WebSocket connection has to be B<ping>-ed to stay alive.
This paramters specifies a positive number of seconds for B<ping> interval.
Default is 30.
=item cfg_websocket_max_payload_size
Maximum payload size for incoming messages in bytes.
Default is 262144.
=item cfg_websocket_deflate_minimum_size
Minimum message size for deflate compression. If message size is less than
this value then it will not be compressed. Default is 96.
=item cfg_websocket_deflate_window_bits
WindowBits parameter for deflate compression. Default is 12.
=item cfg_websocket_deflate_memory_level
MemLevel parameter for deflate compression. Default is 5.
=back
=head1 EXAMPLE
#startup.pl
use WSTest::AppFrontConfig;
use PEF::Front::Config;
use PEF::Front::WebSocket;
use PEF::Front::Route;
PEF::Front::Route::add_route(
get '/' => '/appWs',
);
PEF::Front::Route->to_app();
# $PROJECT_DIR/app/WSTest/WebSocket/Echo.pm
package WSTest::WebSocket::Echo;
sub on_message {
my ($self, $message) = @_;
$self->send($message);
}
1;
# $PROJECT_DIR/templates/ws.html
<html>
<head>
<script language="Javascript">
var s = new WebSocket("ws://[% hostname %]:[% request.port %]/wsEcho");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo" />
<input type="button" value="invia" onClick="invia();" />
<div id="blackboard"
style="width: 640px; height: 480px; background-color: black; color: white; border: solid 2px red; overflow: auto">
</div>
</body>
</html>
# wstest.ini
[uwsgi]
plugins = coroae
chdir = /$PROJECT_DIR
logger = file:log/demo.log
psgi = bin/startup.pl
master = true
processes = 4
coroae = 1000
perl-no-plack = true
psgi-enable-psgix-io = true
uid = $PROJECT_USER
gid = www-data
chmod-socket = 664
=head1 AUTHOR
This module was written and is maintained by Anton Petrusevich.
=head1 Copyright and License
Copyright (c) 2016 Anton Petrusevich. Some Rights Reserved.
This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut