The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

AnyEvent::WebSocket::Server - WebSocket server for AnyEvent

SYNOPSIS

    use AnyEvent::Socket qw(tcp_server);
    use AnyEvent::WebSocket::Server;
    
    my $server = AnyEvent::WebSocket::Server->new();
    
    my $tcp_server;
    $tcp_server = tcp_server undef, 8080, sub {
        my ($fh) = @_;
        $server->establish($fh)->cb(sub {
            my $connection = eval { shift->recv };
            if($@) {
                warn "Invalid connection request: $@\n";
                close($fh);
                return;
            }
            $connection->on(each_message => sub {
                my ($connection, $message) = @_;
                $connection->send($message); ## echo
            });
            $connection->on(finish => sub {
                undef $connection;
            });
        });
    };

DESCRIPTION

This class is an implementation of the WebSocket server in an AnyEvent context.

  • Currently this module supports WebSocket protocol version 13 only. See RFC 6455 for detail.

  • Currently this module does not support SSL/TLS.

CLASS METHODS

$server = AnyEvent::WebSocket::Server->new(%args)

The constructor.

Fields in %args are:

validator => CODE (optional)

A subroutine reference to validate the incoming WebSocket request. If omitted, it accepts the request.

The validator is called like

    @validator_result = $validator->($request)

where $request is a Protocol::WebSocket::Request object.

If you reject the $request, throw an exception.

If you accept the $request, don't throw any exception. The return values of the $validator are sent to the condition variable of establish() method.

OBJECT METHODS

$conn_cv = $server->establish($fh)

Establish a WebSocket connection to a client via the given connection filehandle.

$fh is a filehandle for a connection socket, which is usually obtained by tcp_server() function in AnyEvent::Socket.

Return value $conn_cv is an AnyEvent condition variable.

In success, $conn_cv->recv returns an AnyEvent::WebSocket::Connection object and additional values returned by the validator. In failure (e.g. the client sent a totally invalid request or your validator threw an exception), $conn_cv will croak an error message.

    ($connection, @validator_result) = eval { $conn_cv->recv };
    
    ## or in scalar context, it returns $connection only.
    $connection = eval { $conn_cv->recv };
    
    if($@) {
        my $error = $@;
        ...
        return;
    }
    do_something_with($connection);

You can use $connection to send and receive data through WebSocket. See AnyEvent::WebSocket::Connection for detail.

Note that even if $conn_cv croaks, the connection socket $fh remains intact. You can communicate with the client via $fh unless the client has already closed it.

$conn_cv = $server->establish_psgi($psgi_env, [$fh])

The same as establish() method except that the request is in the form of PSGI environment. This method is experimental. The API may change in the future.

$psgi_env is a PSGI environment object obtained from a PSGI server. $fh is the connection filehandle. If $fh is omitted, $psgi_env->{"psgix.io"} is used for the connection (see PSGI::Extensions).

EXAMPLES

Validator option

The following server accepts WebSocket URLs such as ws://localhost:8080/2013/10.

    use AnyEvent::Socket qw(tcp_server);
    use AnyEvent::WebSocket::Server;
    
    my $server = AnyEvent::WebSocket::Server->new(
        validator => sub {
            my ($req) = @_;  ## Protocol::WebSocket::Request
            
            my $path = $req->resource_name;
            die "Invalid format" if $path !~ m{^/(\d{4})/(\d{2})};
            
            my ($year, $month) = ($1, $2);
            die "Invalid month" if $month <= 0 || $month > 12;
    
            return ($year, $month);
        }
    );
    
    tcp_server undef, 8080, sub {
        my ($fh) = @_;
        $server->establish($fh)->cb(sub {
            my ($conn, $year, $month) = eval { shift->recv };
            if($@) {
                my $error = $@;
                error_response($fh, $error);
                return;
            }
            $conn->send("You are accessing YEAR = $year, MONTH = $month");
            $conn->on(finish => sub { undef $conn });
        });
    };

SEE ALSO

AnyEvent::WebSocket::Client

AnyEvent-based WebSocket client implementation.

Net::WebSocket::Server

Minimalistic stand-alone WebSocket server. It uses its own event loop mechanism.

Net::Async::WebSocket

Stand-alone WebSocket server and client implementation using IO::Async

AUTHOR

Toshio Ito, <toshioito at cpan.org>

REPOSITORY

https://github.com/debug-ito/AnyEvent-WebSocket-Server

ACKNOWLEDGEMENTS

Graham Ollis (plicease) - author of AnyEvent::WebSocket::Client

LICENSE AND COPYRIGHT

Copyright 2013 Toshio Ito.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.