File Coverage

blib/lib/Mercury.pm
Criterion Covered Total %
statement 51 54 94.4
branch 8 12 66.6
condition 3 3 100.0
subroutine 8 9 88.8
pod 1 1 100.0
total 71 79 89.8


line stmt bran cond sub pod time code
1             package Mercury;
2             our $VERSION = '0.014';
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   1090925 use Mojo::Base 'Mojolicious';
  4         10  
  4         28  
29 4     4   162032 use Scalar::Util qw( weaken refaddr );
  4         10  
  4         204  
30 4     4   24 use File::Basename qw( dirname );
  4         7  
  4         226  
31 4     4   25 use File::Spec::Functions qw( catdir );
  4         6  
  4         177  
32 4     4   20 use Mojo::WebSocket 'WS_PING';
  4         9  
  4         2297  
33              
34             sub startup {
35 4     4 1 41506 my ( $app ) = @_;
36 4         27 $app->plugin( 'Config', { default => { broker => { } } } );
37 4         5746 $app->commands->namespaces( [ 'Mercury::Command::mercury' ] );
38              
39 4         239 my $r = $app->routes;
40 4 100       30 if ( my $origin = $app->config->{broker}{allow_origin} ) {
41             # Allow only '*' for wildcards
42 1 50       12 my @origin = map { quotemeta } ref $origin eq 'ARRAY' ? @$origin : $origin;
  1         5  
43 1         4 s/\\\*/.*/g for @origin;
44              
45             $r = $r->under( '/' => sub {
46             #say "Got origin: " . $_[0]->req->headers->origin;
47             #say "Checking against: @origin";
48 15     15   20947 my $origin = $_[0]->req->headers->origin;
49 15 100 100     462 if ( !$origin || !grep { $origin =~ /$_/ } @origin ) {
  10         104  
50 10         52 $_[0]->render(
51             status => '401',
52             text => 'Origin check failed',
53             );
54 10         4136 return;
55             }
56 5         35 return 1;
57 1         14 } );
58             }
59              
60             $app->hook( before_dispatch => sub {
61 37     37   438788 my ( $c ) = @_;
62 37 100       182 if ( $c->tx->is_websocket ) {
63 33         373 weaken $c;
64             my $id = Mojo::IOLoop->recurring( 300, sub {
65 0 0       0 return unless $c;
66 0         0 $c->tx->send([1, 0, 0, 0, WS_PING, 'Still alive!']);
67 33         274 } );
68 33         2183 $c->tx->once( finish => sub { Mojo::IOLoop->remove( $id ) } );
  32         121619  
69             }
70 4         279 } );
71              
72 4         49 $app->plugin( 'Mercury' );
73 4         68 $r->websocket( '/push/*topic' )
74             ->to( controller => 'PushPull', action => 'push' )
75             ->name( 'push' );
76 4         1552 $r->post( '/push/*topic' )
77             ->to( controller => 'PushPull', action => 'post' )
78             ->name( 'push_post' );
79 4         904 $r->websocket( '/pull/*topic' )
80             ->to( controller => 'PushPull', action => 'pull' )
81             ->name( 'pull' );
82              
83 4         891 $r->websocket( '/pub/*topic' )
84             ->to( controller => 'PubSub::Cascade', action => 'publish' )
85             ->name( 'pub' );
86 4         887 $r->post( '/pub/*topic' )
87             ->to( controller => 'PubSub::Cascade', action => 'post' )
88             ->name( 'pub_post' );
89 4         911 $r->websocket( '/sub/*topic' )
90             ->to( controller => 'PubSub::Cascade', action => 'subscribe' )
91             ->name( 'sub' );
92              
93 4         852 $r->websocket( '/bus/*topic' )
94             ->to( controller => 'Bus', action => 'connect' )
95             ->name( 'bus' );
96 4         917 $r->post( '/bus/*topic' )
97             ->to( controller => 'Bus', action => 'post' )
98             ->name( 'bus_post' );
99              
100 4 50       881 if ( $app->mode eq 'development' ) {
101             # Enable the example app
102 4         276 my $root = catdir( dirname( __FILE__ ), 'Mercury' );
103 4         45 $app->static->paths->[0] = catdir( $root, 'public' );
104 4         61 $app->renderer->paths->[0] = catdir( $root, 'templates' );
105 4     0   48 $app->routes->any( '/' )->to( cb => sub { shift->render( 'index' ) } );
  0            
106             }
107             }
108              
109             1;
110              
111             __END__