| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Plack::Runner; |
|
2
|
1
|
|
|
1
|
|
55411
|
use strict; |
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
24
|
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
20
|
|
|
4
|
1
|
|
|
1
|
|
4
|
use Carp (); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
12
|
|
|
5
|
1
|
|
|
1
|
|
364
|
use Plack::Util; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
6
|
1
|
|
|
1
|
|
377
|
use Try::Tiny; |
|
|
1
|
|
|
|
|
1645
|
|
|
|
1
|
|
|
|
|
1064
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
sub new { |
|
9
|
8
|
|
|
8
|
0
|
4230
|
my $class = shift; |
|
10
|
|
|
|
|
|
|
bless { |
|
11
|
|
|
|
|
|
|
env => $ENV{PLACK_ENV}, |
|
12
|
8
|
|
|
|
|
42
|
loader => 'Plack::Loader', |
|
13
|
|
|
|
|
|
|
includes => [], |
|
14
|
|
|
|
|
|
|
modules => [], |
|
15
|
|
|
|
|
|
|
default_middleware => 1, |
|
16
|
|
|
|
|
|
|
@_, |
|
17
|
|
|
|
|
|
|
}, $class; |
|
18
|
|
|
|
|
|
|
} |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# delay the build process for reloader |
|
21
|
|
|
|
|
|
|
sub build(&;$) { |
|
22
|
0
|
|
|
0
|
0
|
0
|
my $block = shift; |
|
23
|
0
|
|
0
|
0
|
|
0
|
my $app = shift || sub { }; |
|
24
|
0
|
|
|
0
|
|
0
|
return sub { $block->($app->()) }; |
|
|
0
|
|
|
|
|
0
|
|
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub parse_options { |
|
28
|
8
|
|
|
8
|
0
|
28
|
my $self = shift; |
|
29
|
|
|
|
|
|
|
|
|
30
|
8
|
|
|
|
|
20
|
local @ARGV = @_; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# From 'prove': Allow cuddling the paths with -I, -M and -e |
|
33
|
8
|
50
|
|
|
|
13
|
@ARGV = map { /^(-[IMe])(.+)/ ? ($1,$2) : $_ } @ARGV; |
|
|
24
|
|
|
|
|
57
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
8
|
|
|
|
|
11
|
my($host, $port, $socket, @listen); |
|
36
|
|
|
|
|
|
|
|
|
37
|
8
|
|
|
|
|
640
|
require Getopt::Long; |
|
38
|
8
|
|
|
|
|
9048
|
my $parser = Getopt::Long::Parser->new( |
|
39
|
|
|
|
|
|
|
config => [ "no_auto_abbrev", "no_ignore_case", "pass_through" ], |
|
40
|
|
|
|
|
|
|
); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
$parser->getoptions( |
|
43
|
|
|
|
|
|
|
"a|app=s" => \$self->{app}, |
|
44
|
|
|
|
|
|
|
"o|host=s" => \$host, |
|
45
|
|
|
|
|
|
|
"p|port=i" => \$port, |
|
46
|
|
|
|
|
|
|
"s|server=s" => \$self->{server}, |
|
47
|
|
|
|
|
|
|
"S|socket=s" => \$socket, |
|
48
|
|
|
|
|
|
|
'l|listen=s@' => \@listen, |
|
49
|
|
|
|
|
|
|
'D|daemonize' => \$self->{daemonize}, |
|
50
|
|
|
|
|
|
|
"E|env=s" => \$self->{env}, |
|
51
|
|
|
|
|
|
|
"e=s" => \$self->{eval}, |
|
52
|
|
|
|
|
|
|
'I=s@' => $self->{includes}, |
|
53
|
|
|
|
|
|
|
'M=s@' => $self->{modules}, |
|
54
|
0
|
|
|
0
|
|
0
|
'r|reload' => sub { $self->{loader} = "Restarter" }, |
|
55
|
0
|
|
|
0
|
|
0
|
'R|Reload=s' => sub { $self->{loader} = "Restarter"; $self->loader->watch(split ",", $_[1]) }, |
|
|
0
|
|
|
|
|
0
|
|
|
56
|
|
|
|
|
|
|
'L|loader=s' => \$self->{loader}, |
|
57
|
|
|
|
|
|
|
"access-log=s" => \$self->{access_log}, |
|
58
|
|
|
|
|
|
|
"path=s" => \$self->{path}, |
|
59
|
|
|
|
|
|
|
"h|help" => \$self->{help}, |
|
60
|
|
|
|
|
|
|
"v|version" => \$self->{version}, |
|
61
|
|
|
|
|
|
|
"default-middleware!" => \$self->{default_middleware}, |
|
62
|
8
|
|
|
|
|
654
|
); |
|
63
|
|
|
|
|
|
|
|
|
64
|
8
|
|
|
|
|
9267
|
my(@options, @argv); |
|
65
|
8
|
|
|
|
|
24
|
while (defined(my $arg = shift @ARGV)) { |
|
66
|
5
|
100
|
|
|
|
17
|
if ($arg =~ s/^--?//) { |
|
67
|
4
|
|
|
|
|
9
|
my @v = split '=', $arg, 2; |
|
68
|
4
|
|
|
|
|
6
|
$v[0] =~ tr/-/_/; |
|
69
|
4
|
100
|
|
|
|
12
|
if (@v == 2) { |
|
|
|
50
|
|
|
|
|
|
|
70
|
2
|
|
|
|
|
7
|
push @options, @v; |
|
71
|
|
|
|
|
|
|
} elsif ($v[0] =~ s/^(disable|enable)_//) { |
|
72
|
2
|
|
|
|
|
10
|
push @options, $v[0], $1 eq 'enable'; |
|
73
|
|
|
|
|
|
|
} else { |
|
74
|
0
|
|
|
|
|
0
|
push @options, $v[0], shift @ARGV; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
} else { |
|
77
|
1
|
|
|
|
|
3
|
push @argv, $arg; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
8
|
|
|
|
|
20
|
push @options, $self->mangle_host_port_socket($host, $port, $socket, @listen); |
|
82
|
8
|
100
|
|
|
|
24
|
push @options, daemonize => 1 if $self->{daemonize}; |
|
83
|
|
|
|
|
|
|
|
|
84
|
8
|
|
|
|
|
9
|
$self->{options} = \@options; |
|
85
|
8
|
|
|
|
|
36
|
$self->{argv} = \@argv; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub set_options { |
|
89
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
90
|
0
|
|
|
|
|
0
|
push @{$self->{options}}, @_; |
|
|
0
|
|
|
|
|
0
|
|
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub mangle_host_port_socket { |
|
94
|
8
|
|
|
8
|
0
|
16
|
my($self, $host, $port, $socket, @listen) = @_; |
|
95
|
|
|
|
|
|
|
|
|
96
|
8
|
|
|
|
|
13
|
for my $listen (reverse @listen) { |
|
97
|
5
|
100
|
|
|
|
16
|
if ($listen =~ /:\d+$/) { |
|
98
|
3
|
|
|
|
|
9
|
($host, $port) = split /:/, $listen, 2; |
|
99
|
3
|
100
|
|
|
|
9
|
$host = undef if $host eq ''; |
|
100
|
|
|
|
|
|
|
} else { |
|
101
|
2
|
|
33
|
|
|
8
|
$socket ||= $listen; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
8
|
100
|
|
|
|
14
|
unless (@listen) { |
|
106
|
4
|
100
|
|
|
|
9
|
if ($socket) { |
|
107
|
1
|
|
|
|
|
2
|
@listen = ($socket); |
|
108
|
|
|
|
|
|
|
} else { |
|
109
|
3
|
|
100
|
|
|
9
|
$port ||= 5000; |
|
110
|
3
|
100
|
|
|
|
11
|
@listen = ($host ? "$host:$port" : ":$port"); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
8
|
|
|
|
|
29
|
return host => $host, port => $port, listen => \@listen, socket => $socket; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub version_cb { |
|
118
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
119
|
|
|
|
|
|
|
$self->{version_cb} || sub { |
|
120
|
0
|
|
|
0
|
|
|
require Plack; |
|
121
|
0
|
|
|
|
|
|
print "Plack $Plack::VERSION\n"; |
|
122
|
0
|
0
|
|
|
|
|
}; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub setup { |
|
126
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
127
|
|
|
|
|
|
|
|
|
128
|
0
|
0
|
|
|
|
|
if ($self->{help}) { |
|
129
|
0
|
|
|
|
|
|
require Pod::Usage; |
|
130
|
0
|
|
|
|
|
|
Pod::Usage::pod2usage(0); |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
|
if ($self->{version}) { |
|
134
|
0
|
|
|
|
|
|
$self->version_cb->(); |
|
135
|
0
|
|
|
|
|
|
exit; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
0
|
0
|
|
|
|
|
if (@{$self->{includes}}) { |
|
|
0
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
require lib; |
|
140
|
0
|
|
|
|
|
|
lib->import(@{$self->{includes}}); |
|
|
0
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
0
|
0
|
|
|
|
|
if ($self->{eval}) { |
|
144
|
0
|
|
|
|
|
|
push @{$self->{modules}}, 'Plack::Builder'; |
|
|
0
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
for (@{$self->{modules}}) { |
|
|
0
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
my($module, @import) = split /[=,]/; |
|
149
|
0
|
0
|
|
|
|
|
eval "require $module" or die $@; |
|
150
|
0
|
|
|
|
|
|
$module->import(@import); |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub locate_app { |
|
155
|
0
|
|
|
0
|
0
|
|
my($self, @args) = @_; |
|
156
|
|
|
|
|
|
|
|
|
157
|
0
|
|
0
|
|
|
|
my $psgi = $self->{app} || $args[0]; |
|
158
|
|
|
|
|
|
|
|
|
159
|
0
|
0
|
|
|
|
|
if (ref $psgi eq 'CODE') { |
|
160
|
0
|
|
|
0
|
|
|
return sub { $psgi }; |
|
|
0
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
0
|
0
|
|
|
|
|
if ($self->{eval}) { |
|
164
|
0
|
0
|
|
|
|
|
$self->loader->watch("lib") if -e "lib"; |
|
165
|
|
|
|
|
|
|
return build { |
|
166
|
1
|
|
|
1
|
|
6
|
no strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
19
|
|
|
167
|
1
|
|
|
1
|
|
3
|
no warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
804
|
|
|
168
|
0
|
|
|
0
|
|
|
my $eval = "builder { $self->{eval};"; |
|
169
|
0
|
0
|
|
|
|
|
$eval .= "Plack::Util::load_psgi(\$psgi);" if $psgi; |
|
170
|
0
|
|
|
|
|
|
$eval .= "}"; |
|
171
|
0
|
0
|
|
|
|
|
eval $eval or die $@; |
|
172
|
0
|
|
|
|
|
|
}; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
0
|
|
0
|
|
|
|
$psgi ||= "app.psgi"; |
|
176
|
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
require File::Basename; |
|
178
|
0
|
|
|
|
|
|
my $lib = File::Basename::dirname($psgi) . "/lib"; |
|
179
|
0
|
0
|
|
|
|
|
$self->loader->watch($lib) if -e $lib; |
|
180
|
0
|
|
|
|
|
|
$self->loader->watch($psgi); |
|
181
|
0
|
|
|
0
|
|
|
build { Plack::Util::load_psgi $psgi }; |
|
|
0
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub watch { |
|
185
|
0
|
|
|
0
|
0
|
|
my($self, @dir) = @_; |
|
186
|
|
|
|
|
|
|
|
|
187
|
0
|
|
|
|
|
|
push @{$self->{watch}}, @dir |
|
188
|
0
|
0
|
|
|
|
|
if $self->{loader} eq 'Restarter'; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub apply_middleware { |
|
192
|
0
|
|
|
0
|
0
|
|
my($self, $app, $class, @args) = @_; |
|
193
|
|
|
|
|
|
|
|
|
194
|
0
|
|
|
|
|
|
my $mw_class = Plack::Util::load_class($class, 'Plack::Middleware'); |
|
195
|
0
|
|
|
0
|
|
|
build { $mw_class->wrap($_[0], @args) } $app; |
|
|
0
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub prepare_devel { |
|
199
|
0
|
|
|
0
|
0
|
|
my($self, $app) = @_; |
|
200
|
|
|
|
|
|
|
|
|
201
|
0
|
0
|
|
|
|
|
if ($self->{default_middleware}) { |
|
202
|
0
|
|
|
|
|
|
$app = $self->apply_middleware($app, 'Lint'); |
|
203
|
0
|
|
|
|
|
|
$app = $self->apply_middleware($app, 'StackTrace'); |
|
204
|
0
|
0
|
0
|
|
|
|
if (!$ENV{GATEWAY_INTERFACE} and !$self->{access_log}) { |
|
205
|
0
|
|
|
|
|
|
$app = $self->apply_middleware($app, 'AccessLog'); |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
push @{$self->{options}}, server_ready => sub { |
|
210
|
0
|
|
|
0
|
|
|
my($args) = @_; |
|
211
|
0
|
|
0
|
|
|
|
my $name = $args->{server_software} || ref($args); # $args is $server |
|
212
|
0
|
|
0
|
|
|
|
my $host = $args->{host} || 0; |
|
213
|
0
|
|
0
|
|
|
|
my $proto = $args->{proto} || 'http'; |
|
214
|
0
|
|
|
|
|
|
print STDERR "$name: Accepting connections at $proto://$host:$args->{port}/\n"; |
|
215
|
0
|
|
|
|
|
|
}; |
|
216
|
|
|
|
|
|
|
|
|
217
|
0
|
|
|
|
|
|
$app; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub loader { |
|
221
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
222
|
0
|
|
0
|
|
|
|
$self->{_loader} ||= Plack::Util::load_class($self->{loader}, 'Plack::Loader')->new; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub load_server { |
|
226
|
0
|
|
|
0
|
0
|
|
my($self, $loader) = @_; |
|
227
|
|
|
|
|
|
|
|
|
228
|
0
|
0
|
|
|
|
|
if ($self->{server}) { |
|
229
|
0
|
|
|
|
|
|
return $loader->load($self->{server}, @{$self->{options}}); |
|
|
0
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
} else { |
|
231
|
0
|
|
|
|
|
|
return $loader->auto(@{$self->{options}}); |
|
|
0
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub run { |
|
236
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
237
|
|
|
|
|
|
|
|
|
238
|
0
|
0
|
|
|
|
|
unless (ref $self) { |
|
239
|
0
|
|
|
|
|
|
$self = $self->new; |
|
240
|
0
|
|
|
|
|
|
$self->parse_options(@_); |
|
241
|
0
|
|
|
|
|
|
return $self->run; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
0
|
0
|
|
|
|
|
unless ($self->{options}) { |
|
245
|
0
|
|
|
|
|
|
$self->parse_options(); |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
0
|
0
|
|
|
|
|
my @args = @_ ? @_ : @{$self->{argv}}; |
|
|
0
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
|
$self->setup; |
|
251
|
|
|
|
|
|
|
|
|
252
|
0
|
|
|
|
|
|
my $app = $self->locate_app(@args); |
|
253
|
|
|
|
|
|
|
|
|
254
|
0
|
0
|
|
|
|
|
if ($self->{path}) { |
|
255
|
0
|
|
|
|
|
|
require Plack::App::URLMap; |
|
256
|
|
|
|
|
|
|
$app = build { |
|
257
|
0
|
|
|
0
|
|
|
my $urlmap = Plack::App::URLMap->new; |
|
258
|
0
|
|
|
|
|
|
$urlmap->mount($self->{path} => $_[0]); |
|
259
|
0
|
|
|
|
|
|
$urlmap->to_app; |
|
260
|
0
|
|
|
|
|
|
} $app; |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
0
|
|
0
|
|
|
|
$ENV{PLACK_ENV} ||= $self->{env} || 'development'; |
|
|
|
|
0
|
|
|
|
|
|
264
|
0
|
0
|
|
|
|
|
if ($ENV{PLACK_ENV} eq 'development') { |
|
265
|
0
|
|
|
|
|
|
$app = $self->prepare_devel($app); |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
0
|
0
|
|
|
|
|
if ($self->{access_log}) { |
|
269
|
|
|
|
|
|
|
open my $logfh, ">>", $self->{access_log} |
|
270
|
0
|
0
|
|
|
|
|
or die "open($self->{access_log}): $!"; |
|
271
|
0
|
|
|
|
|
|
$logfh->autoflush(1); |
|
272
|
0
|
|
|
0
|
|
|
$app = $self->apply_middleware($app, 'AccessLog', logger => sub { $logfh->print( @_ ) }); |
|
|
0
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
0
|
|
|
|
|
|
my $loader = $self->loader; |
|
276
|
0
|
|
|
|
|
|
$loader->preload_app($app); |
|
277
|
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
|
my $server = $self->load_server($loader); |
|
279
|
0
|
|
|
|
|
|
$loader->run($server); |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
1; |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
__END__ |