File Coverage

blib/lib/Dancer2/Plugin/WebSocket.pm
Criterion Covered Total %
statement 31 42 73.8
branch 1 4 25.0
condition n/a
subroutine 7 9 77.7
pod 2 2 100.0
total 41 57 71.9


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::WebSocket;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: add a websocket interface to your Dancers app
4             $Dancer2::Plugin::WebSocket::VERSION = '0.1.3';
5              
6 1     1   438 use Plack::App::WebSocket;
  1         82113  
  1         37  
7              
8 1     1   538 use Dancer2::Plugin;
  1         13595  
  1         10  
9              
10             has serializer => (
11             is => 'ro',
12             from_config => 1,
13             coerce => sub {
14             my $serializer = shift or return undef;
15             require JSON::MaybeXS;
16             JSON::MaybeXS->new( ref $serializer ? %$serializer : () );
17             },
18             );
19              
20             has mount_path => (
21             is => 'ro',
22             from_config => sub { '/ws' },
23             );
24              
25              
26             has 'on_'.$_ => (
27             is => 'rw',
28             plugin_keyword => 'websocket_on_'.$_,
29             default => sub { sub { } },
30             ) for qw/
31             open
32             message
33             close
34             /;
35              
36             has 'on_error' => (
37             is => 'rw',
38             plugin_keyword => 'websocket_on_error',
39             default => sub { sub {
40             my $env = shift;
41             return [500,
42             ["Content-Type" => "text/plain"],
43             ["Error: " . $env->{"plack.app.websocket.error"}]];
44             }
45             },
46             );
47              
48             has connections => (
49             is => 'ro',
50             default => sub{ {} },
51             );
52              
53              
54             sub websocket_url :PluginKeyword {
55 0     0 1 0 my $self = shift;
56 0         0 my $request = $self->app->request;
57 0 0       0 my $proto = $request->secure ? 'wss://' : 'ws://';
58 0         0 my $address = $proto . $request->host . $self->mount_path;
59              
60 0         0 return $address;
61 1     1   3631 }
  1         2  
  1         17  
62              
63              
64             sub websocket_mount :PluginKeyword {
65 1     1 1 8 my $self = shift;
66              
67             return
68             $self->mount_path => Plack::App::WebSocket->new(
69 0     0   0 on_error => sub { $self->on_error->(@_) },
70             on_establish => sub {
71 1     1   155157 my $conn = shift; ## Plack::App::WebSocket::Connection object
72 1         2 my $env = shift; ## PSGI env
73              
74 1         10 require Moo::Role;
75              
76 1         8 Moo::Role->apply_roles_to_object(
77             $conn, 'Dancer2::Plugin::WebSocket::Connection'
78             );
79 1         2036 $conn->manager($self);
80 1         39 $conn->serializer($self->serializer);
81 1         84 $self->connections->{$conn->id} = $conn;
82              
83 1         11 $self->on_open->( $conn, $env, @_ );
84              
85             $conn->on(
86             message => sub {
87 1         4955 my( $conn, $message ) = @_;
88 1 50       13 if( my $s = $conn->serializer ) {
89 1         9 $message = $s->decode($message);
90             }
91 1     1   679 use Try::Tiny;
  1         3  
  1         214  
92             try {
93 1         61 $self->on_message->( $conn, $message );
94             }
95             catch {
96 0           warn $_;
97 0           die $_;
98 1         11 };
99             },
100             finish => sub {
101 0           $self->on_close->($conn);
102 0           delete $self->connections->{$conn->id};
103 0           $conn = undef;
104             },
105 1         27 );
106             }
107 1         24 )->to_app;
108              
109 1     1   12 }
  1         4  
  1         5  
110              
111              
112             1;
113              
114             __END__