File Coverage

blib/lib/Mercury.pm
Criterion Covered Total %
statement 52 55 94.5
branch 8 12 66.6
condition 3 3 100.0
subroutine 8 9 88.8
pod 1 1 100.0
total 72 80 90.0


line stmt bran cond sub pod time code
1             package Mercury;
2             our $VERSION = '0.015';
3             # ABSTRACT: Main broker application class
4              
5             #pod =head1 SYNOPSIS
6             #pod
7             #pod # Start the broker
8             #pod $ mercury broker
9             #pod
10             #pod # To get help
11             #pod $ mercury help broker
12             #pod
13             #pod =head1 DESCRIPTION
14             #pod
15             #pod This is the main broker application class. This is the standard broker
16             #pod application that is started when you use C.
17             #pod
18             #pod To learn how to use this application to broker messages, see L
19             #pod Mercury documentation|mercury>. For how to start the broker application,
20             #pod see L
21             #pod or run C.
22             #pod
23             #pod To learn how to create a custom message broker to integrate authentication,
24             #pod logging, and other customizations, see L.
25             #pod
26             #pod =cut
27              
28 4     4   1491431 use Mojo::Base 'Mojolicious';
  4         12  
  4         25  
29 4     4   184288 use Scalar::Util qw( weaken refaddr );
  4         9  
  4         260  
30 4     4   27 use File::Basename qw( dirname );
  4         8  
  4         239  
31 4     4   27 use File::Spec::Functions qw( catdir );
  4         16  
  4         217  
32 4     4   22 use Mojo::WebSocket 'WS_PING';
  4         14  
  4         2455  
33              
34             sub startup {
35 4     4 1 55430 my ( $app ) = @_;
36 4         43 $app->log( Mojo::Log->new ); # Log only to STDERR
37 4         195 $app->plugin( 'Config', { default => { broker => { } } } );
38 4         7562 $app->commands->namespaces( [ 'Mercury::Command::mercury' ] );
39              
40 4         232 my $r = $app->routes;
41 4 100       36 if ( my $origin = $app->config->{broker}{allow_origin} ) {
42             # Allow only '*' for wildcards
43 1 50       18 my @origin = map { quotemeta } ref $origin eq 'ARRAY' ? @$origin : $origin;
  1         8  
44 1         7 s/\\\*/.*/g for @origin;
45              
46             $r = $r->under( '/' => sub {
47             #say "Got origin: " . $_[0]->req->headers->origin;
48             #say "Checking against: @origin";
49 15     15   32703 my $origin = $_[0]->req->headers->origin;
50 15 100 100     736 if ( !$origin || !grep { $origin =~ /$_/ } @origin ) {
  10         141  
51 10         89 $_[0]->render(
52             status => '401',
53             text => 'Origin check failed',
54             );
55 10         6352 return;
56             }
57 5         51 return 1;
58 1         19 } );
59             }
60              
61             $app->hook( before_dispatch => sub {
62 37     37   602207 my ( $c ) = @_;
63 37 100       230 if ( $c->tx->is_websocket ) {
64 33         522 weaken $c;
65             my $id = Mojo::IOLoop->recurring( 300, sub {
66 0 0       0 return unless $c;
67 0         0 $c->tx->send([1, 0, 0, 0, WS_PING, 'Still alive!']);
68 33         401 } );
69 33         3252 $c->tx->once( finish => sub { Mojo::IOLoop->remove( $id ) } );
  32         190971  
70             }
71 4         379 } );
72              
73 4         69 $app->plugin( 'Mercury' );
74 4         84 $r->websocket( '/push/*topic' )
75             ->to( controller => 'PushPull', action => 'push' )
76             ->name( 'push' );
77 4         1725 $r->post( '/push/*topic' )
78             ->to( controller => 'PushPull', action => 'post' )
79             ->name( 'push_post' );
80 4         1261 $r->websocket( '/pull/*topic' )
81             ->to( controller => 'PushPull', action => 'pull' )
82             ->name( 'pull' );
83              
84 4         1474 $r->websocket( '/pub/*topic' )
85             ->to( controller => 'PubSub::Cascade', action => 'publish' )
86             ->name( 'pub' );
87 4         1319 $r->post( '/pub/*topic' )
88             ->to( controller => 'PubSub::Cascade', action => 'post' )
89             ->name( 'pub_post' );
90 4         1286 $r->websocket( '/sub/*topic' )
91             ->to( controller => 'PubSub::Cascade', action => 'subscribe' )
92             ->name( 'sub' );
93              
94 4         1318 $r->websocket( '/bus/*topic' )
95             ->to( controller => 'Bus', action => 'connect' )
96             ->name( 'bus' );
97 4         1249 $r->post( '/bus/*topic' )
98             ->to( controller => 'Bus', action => 'post' )
99             ->name( 'bus_post' );
100              
101 4 50       1203 if ( $app->mode eq 'development' ) {
102             # Enable the example app
103 4         278 my $root = catdir( dirname( __FILE__ ), 'Mercury' );
104 4         36 $app->static->paths->[0] = catdir( $root, 'public' );
105 4         68 $app->renderer->paths->[0] = catdir( $root, 'templates' );
106 4     0   51 $app->routes->any( '/' )->to( cb => sub { shift->render( 'index' ) } );
  0            
107             }
108             }
109              
110             1;
111              
112             __END__