line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Kelp::Module::Symbiosis::Base; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $VERSION = '1.12'; |
4
|
|
|
|
|
|
|
|
5
|
5
|
|
|
5
|
|
4847
|
use Kelp::Base qw(Kelp::Module); |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
35
|
|
6
|
5
|
|
|
5
|
|
916
|
use Kelp::Module::Symbiosis::_Util; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
1468
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
attr -middleware => sub { [] }; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# should likely be overriden for a more suitable name |
11
|
|
|
|
|
|
|
# won't break backcompat though |
12
|
3
|
|
|
3
|
1
|
37
|
sub name { ref shift } |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub run |
15
|
|
|
|
|
|
|
{ |
16
|
27
|
|
|
27
|
1
|
53
|
my ($self) = shift; |
17
|
|
|
|
|
|
|
|
18
|
27
|
|
|
|
|
83
|
my $app = $self->psgi(@_); |
19
|
27
|
|
|
|
|
257
|
return Kelp::Module::Symbiosis::_Util::wrap($self, $app); |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub psgi |
23
|
|
|
|
|
|
|
{ |
24
|
0
|
|
|
0
|
1
|
0
|
die __PACKAGE__ . " - psgi needs to be reimplemented"; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub build |
28
|
|
|
|
|
|
|
{ |
29
|
8
|
|
|
8
|
1
|
56670
|
my ($self, %args) = @_; |
30
|
|
|
|
|
|
|
|
31
|
8
|
50
|
|
|
|
29
|
die 'Kelp::Module::Symbiosis needs to be loaded before ' . ref $self |
32
|
|
|
|
|
|
|
unless $self->app->can('symbiosis'); |
33
|
|
|
|
|
|
|
|
34
|
8
|
|
|
|
|
87
|
Kelp::Module::Symbiosis::_Util::load_middleware($self, %args); |
35
|
|
|
|
|
|
|
|
36
|
8
|
|
|
|
|
22
|
$self->app->symbiosis->_link($self->name, $self, $args{mount}); |
37
|
8
|
|
|
|
|
26
|
return; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
1; |
41
|
|
|
|
|
|
|
__END__ |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head1 NAME |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Kelp::Module::Symbiosis::Base - Base class for symbiotic modules |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 SYNOPSIS |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
package Kelp::Module::MyModule; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
use Kelp::Base qw(Kelp::Module::Symbiosis::Base); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub psgi |
54
|
|
|
|
|
|
|
{ |
55
|
|
|
|
|
|
|
# write code that returns psgi application without middlewares |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub build |
59
|
|
|
|
|
|
|
{ |
60
|
|
|
|
|
|
|
my ($self, %args) = @_; |
61
|
|
|
|
|
|
|
$self->SUPER::build(%args); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# write initialization code as usual |
64
|
|
|
|
|
|
|
$self->register(some_method => sub { ... }); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 DESCRIPTION |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
This class serves as a base for a Kelp module that is supposed to be ran as a standalone Plack application (mounted separately). It takes care of middleware management, mounting into Symbiosis manager and some basic initialization chores. To write a new module that introduces a standalone Plack application as a Kelp module, simply extend this class and override methods: C<psgi build name> (see below for details). |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head2 Purpose |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
It is a base for Kelp modules that are meant to be used with Symbiosis - it inherits from L<Kelp::Module>. It can also come very handy because of the built in middleware handling and access to Kelp application's configuration. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 METHODS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=head2 run |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sig: run($self) |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Calls I<psgi()> and wraps its contents in middlewares. Returns a Plack application. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head2 psgi |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sig: psgi($self, @more_data) |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
By default, this method will throw an exception. It has to be replaced with an actual application producing code in the child class. The resulting application will be wrapped in middlewares from config in I<run()>. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
B<Must be reimplemented> in a module. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 build |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sig: build($self, %args) |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Standard Kelp module building method. When reimplementing it's best to call parent's implementation, as middleware initialization happens in base implementation. |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
B<Should be reimplemented> in a module. If it isn't, no extra methods will be added to the Kelp instance, but all the middleware and module registration in Symbiosis will happen anyway. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 name |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sig: name($self) |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
I<new in 1.10> |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Returns a name of a module - a string. This name will be available in L<Kelp::Module::Symbiosis/loaded> hash as a key, containing the module instance as a value. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
B<Should be reimplemented> in a module. If it isn't, it will return the name of the package. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head2 middleware |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sig: middleware($self) |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Returns an array containing all the middlewares in format: C<[ middleware_class, { middleware_config } ]>. By default, this config comes from module configuration. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 CONFIGURATION |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
example configuration could look like this (for L<Kelp::Module::WebSocket::AnyEvent>): |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
modules => [qw/JSON Symbiosis WebSocket::AnyEvent/], |
120
|
|
|
|
|
|
|
modules_init => { |
121
|
|
|
|
|
|
|
Symbiosis => { |
122
|
|
|
|
|
|
|
mount => undef, # kelp will be mounted manually under different path |
123
|
|
|
|
|
|
|
}, |
124
|
|
|
|
|
|
|
"WebSocket::AnyEvent" => { |
125
|
|
|
|
|
|
|
serializer => "json", |
126
|
|
|
|
|
|
|
middleware => [qw/Recorder/], |
127
|
|
|
|
|
|
|
middleware_init => { |
128
|
|
|
|
|
|
|
Recorder => { output => "~/recorder.out" }, |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
}, |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 middleware, middleware_init |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Middleware specs for this application - see above example. Every module basing on this class can specify its own set of middlewares. They are configured exactly the same as middlewares in Kelp. There's currently no standarized way to retrieve middleware configurations from Kelp into another application (to wrap that application in the same middleware as Kelp), so custom code is needed if such need arise. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head2 mount |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
modules_init => { |
140
|
|
|
|
|
|
|
"Symbiotic::Module" => { |
141
|
|
|
|
|
|
|
mount => '/path', |
142
|
|
|
|
|
|
|
... |
143
|
|
|
|
|
|
|
}, |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
I<new in 1.10> |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Should be a string value. If specified, the module will be automatically mounted under that path - there will be no need to call that explicitly, and it will work like: C<< $kelp->symbiosis->mount($path => $module); >>. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head1 SEE ALSO |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=over 2 |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item * L<Kelp::Module::Symbiosis>, the module manager |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=back |