line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Web::Simple::Application; |
2
|
|
|
|
|
|
|
|
3
|
15
|
|
|
15
|
|
74
|
use Scalar::Util 'weaken'; |
|
15
|
|
|
|
|
23
|
|
|
15
|
|
|
|
|
875
|
|
4
|
|
|
|
|
|
|
|
5
|
15
|
|
|
15
|
|
70
|
use Moo; |
|
15
|
|
|
|
|
23
|
|
|
15
|
|
|
|
|
89
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
has 'config' => ( |
8
|
|
|
|
|
|
|
is => 'ro', |
9
|
|
|
|
|
|
|
default => sub { |
10
|
|
|
|
|
|
|
my ($self) = @_; |
11
|
|
|
|
|
|
|
+{ $self->default_config } |
12
|
|
|
|
|
|
|
}, |
13
|
|
|
|
|
|
|
trigger => sub { |
14
|
|
|
|
|
|
|
my ($self, $value) = @_; |
15
|
|
|
|
|
|
|
my %default = $self->default_config; |
16
|
|
|
|
|
|
|
my @not = grep !exists $value->{$_}, keys %default; |
17
|
|
|
|
|
|
|
@{$value}{@not} = @default{@not}; |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
); |
20
|
|
|
|
|
|
|
|
21
|
14
|
|
|
14
|
1
|
351
|
sub default_config { () } |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has '_dispatcher' => (is => 'lazy'); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub _build__dispatcher { |
26
|
15
|
|
|
15
|
|
6317
|
my $self = shift; |
27
|
15
|
|
|
|
|
12673
|
require Web::Dispatch; |
28
|
15
|
|
|
|
|
213
|
my $final = $self->_build_final_dispatcher; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# We need to weaken both the copy of $self that the |
31
|
|
|
|
|
|
|
# app parameter will close over and the copy that'll |
32
|
|
|
|
|
|
|
# be passed through as a node argument. |
33
|
|
|
|
|
|
|
# |
34
|
|
|
|
|
|
|
# To ensure that this doesn't then result in us being |
35
|
|
|
|
|
|
|
# DESTROYed unexpectedly early, our to_psgi_app method |
36
|
|
|
|
|
|
|
# closes back over $self |
37
|
|
|
|
|
|
|
|
38
|
15
|
|
|
|
|
68
|
weaken($self); |
39
|
|
|
|
|
|
|
my %dispatch_args = ( |
40
|
65
|
|
|
65
|
|
302
|
dispatch_app => sub { $self->dispatch_request(@_), $final }, |
41
|
15
|
|
|
|
|
103
|
dispatch_object => $self |
42
|
|
|
|
|
|
|
); |
43
|
15
|
|
|
|
|
94
|
weaken($dispatch_args{dispatch_object}); |
44
|
15
|
|
|
|
|
94
|
Web::Dispatch->new(%dispatch_args); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _build_final_dispatcher { |
48
|
15
|
|
|
15
|
|
71
|
[ 404, [ 'Content-type', 'text/plain' ], [ 'Not found' ] ] |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub run_if_script { |
52
|
|
|
|
|
|
|
# ->to_psgi_app is true for require() but also works for plackup |
53
|
1
|
50
|
|
1
|
1
|
12
|
return $_[0]->to_psgi_app if caller(1); |
54
|
0
|
0
|
|
|
|
0
|
my $self = ref($_[0]) ? $_[0] : $_[0]->new; |
55
|
0
|
|
|
|
|
0
|
$self->run(@_); |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub _run_cgi { |
59
|
2
|
|
|
2
|
|
5
|
my $self = shift; |
60
|
2
|
|
|
|
|
902
|
require Plack::Handler::CGI; |
61
|
2
|
|
|
|
|
1254
|
Plack::Handler::CGI->new->run($self->to_psgi_app); |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub _run_fcgi { |
65
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
66
|
0
|
|
|
|
|
0
|
require Plack::Handler::FCGI; |
67
|
0
|
|
|
|
|
0
|
Plack::Handler::FCGI->new->run($self->to_psgi_app); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub to_psgi_app { |
71
|
66
|
100
|
|
66
|
1
|
251
|
my $self = ref($_[0]) ? $_[0] : $_[0]->new; |
72
|
66
|
|
|
|
|
1371
|
my $app = $self->_dispatcher->to_app; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Close over $self to keep $self alive even though |
75
|
|
|
|
|
|
|
# we weakened the copies the dispatcher has; the |
76
|
|
|
|
|
|
|
# if 0 causes the ops to be optimised away to |
77
|
|
|
|
|
|
|
# minimise the performance impact and avoid void |
78
|
|
|
|
|
|
|
# context warnings while still doing the closing |
79
|
|
|
|
|
|
|
# over part. As Mithaldu said: "Gnarly." ... |
80
|
|
|
|
|
|
|
|
81
|
66
|
|
|
65
|
|
476
|
return sub { $self if 0; goto &$app; }; |
|
65
|
|
|
|
|
82048
|
|
|
65
|
|
|
|
|
244
|
|
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub run { |
85
|
2
|
|
|
2
|
1
|
20807
|
my $self = shift; |
86
|
2
|
50
|
33
|
|
|
48
|
if ( |
|
|
50
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
87
|
|
|
|
|
|
|
$ENV{PHP_FCGI_CHILDREN} || $ENV{FCGI_ROLE} || $ENV{FCGI_SOCKET_PATH} |
88
|
|
|
|
|
|
|
|| ( -S STDIN && !$ENV{GATEWAY_INTERFACE} ) |
89
|
|
|
|
|
|
|
# If STDIN is a socket, almost certainly FastCGI, except for mod_cgid |
90
|
|
|
|
|
|
|
) { |
91
|
0
|
|
|
|
|
0
|
return $self->_run_fcgi; |
92
|
|
|
|
|
|
|
} elsif ($ENV{GATEWAY_INTERFACE}) { |
93
|
2
|
|
|
|
|
19
|
return $self->_run_cgi; |
94
|
|
|
|
|
|
|
} |
95
|
0
|
0
|
0
|
|
|
0
|
unless (@ARGV && $ARGV[0] =~ m{(^[A-Z/])|\@}) { |
96
|
0
|
|
|
|
|
0
|
return $self->_run_cli(@ARGV); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
0
|
my @args = @ARGV; |
100
|
|
|
|
|
|
|
|
101
|
0
|
0
|
|
|
|
0
|
unshift(@args, 'GET') if $args[0] !~ /^[A-Z]/; |
102
|
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
0
|
$self->_run_cli_test_request(@args); |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub _test_request_spec_to_http_request { |
107
|
60
|
|
|
60
|
|
134
|
my ($self, $method, $path, @rest) = @_; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# if it's a reference, assume a request object |
110
|
60
|
100
|
|
|
|
232
|
return $method if ref($method); |
111
|
|
|
|
|
|
|
|
112
|
47
|
100
|
|
|
|
167
|
if ($path =~ s/^(.*?)\@//) { |
113
|
2
|
|
|
|
|
5
|
my $basic = $1; |
114
|
2
|
|
|
|
|
7
|
require MIME::Base64; |
115
|
2
|
|
|
|
|
56
|
unshift @rest, 'Authorization:', 'Basic '.MIME::Base64::encode($basic); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
47
|
|
|
|
|
270
|
my $request = HTTP::Request->new($method => $path); |
119
|
|
|
|
|
|
|
|
120
|
47
|
|
|
|
|
52953
|
my @params; |
121
|
|
|
|
|
|
|
|
122
|
47
|
|
|
|
|
193
|
while (my ($header, $value) = splice(@rest, 0, 2)) { |
123
|
4
|
100
|
|
|
|
19
|
unless ($header =~ s/:$//) { |
124
|
2
|
|
|
|
|
6
|
push @params, $header, $value; |
125
|
|
|
|
|
|
|
} |
126
|
4
|
|
|
|
|
9
|
$header =~ s/_/-/g; |
127
|
4
|
50
|
|
|
|
13
|
if ($header eq 'Content') { |
128
|
0
|
|
|
|
|
0
|
$request->content($value); |
129
|
|
|
|
|
|
|
} else { |
130
|
4
|
|
|
|
|
15
|
$request->headers->push_header($header, $value); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
47
|
100
|
100
|
|
|
439
|
if (($method eq 'POST' or $method eq 'PUT') and @params) { |
|
|
|
100
|
|
|
|
|
135
|
2
|
|
|
|
|
4
|
my $content = do { |
136
|
2
|
|
|
|
|
11
|
require URI; |
137
|
2
|
|
|
|
|
8
|
my $url = URI->new('http:'); |
138
|
2
|
|
|
|
|
104
|
$url->query_form(@params); |
139
|
2
|
|
|
|
|
215
|
$url->query; |
140
|
|
|
|
|
|
|
}; |
141
|
2
|
|
|
|
|
27
|
$request->header('Content-Type' => 'application/x-www-form-urlencoded'); |
142
|
2
|
|
|
|
|
87
|
$request->header('Content-Length' => length($content)); |
143
|
2
|
|
|
|
|
76
|
$request->content($content); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
47
|
|
|
|
|
130
|
return $request; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub run_test_request { |
150
|
60
|
|
|
60
|
1
|
1472388
|
my ($self, @req) = @_; |
151
|
|
|
|
|
|
|
|
152
|
60
|
|
|
|
|
5557
|
require HTTP::Request; |
153
|
|
|
|
|
|
|
|
154
|
60
|
|
|
|
|
163434
|
require Plack::Test; |
155
|
|
|
|
|
|
|
|
156
|
60
|
|
|
|
|
3761
|
my $request = $self->_test_request_spec_to_http_request(@req); |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Plack::Test::test_psgi( |
159
|
60
|
|
|
60
|
|
296693
|
$self->to_psgi_app, sub { shift->($request) } |
160
|
60
|
|
|
|
|
229
|
); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub _run_cli_test_request { |
164
|
0
|
|
|
0
|
|
|
my ($self, @req) = @_; |
165
|
0
|
|
|
|
|
|
my $response = $self->run_test_request(@req); |
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
binmode(STDOUT); binmode(STDERR); # for win32 |
|
0
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
print STDERR $response->status_line."\n"; |
170
|
0
|
|
|
|
|
|
print STDERR $response->headers_as_string("\n")."\n"; |
171
|
0
|
|
|
|
|
|
my $content = $response->content; |
172
|
0
|
0
|
0
|
|
|
|
$content .= "\n" if length($content) and $content !~ /\n\z/; |
173
|
0
|
0
|
|
|
|
|
print STDOUT $content if $content; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _run_cli { |
177
|
0
|
|
|
0
|
|
|
my $self = shift; |
178
|
0
|
|
|
|
|
|
die $self->_cli_usage; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub _cli_usage { |
182
|
0
|
|
|
0
|
|
|
"To run this script in CGI test mode, pass a URL path beginning with /:\n". |
183
|
|
|
|
|
|
|
"\n". |
184
|
|
|
|
|
|
|
" $0 /some/path\n". |
185
|
|
|
|
|
|
|
" $0 /\n" |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
1; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 NAME |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Web::Simple::Application - A base class for your Web-Simple application |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head1 DESCRIPTION |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
This is a base class for your L application. You probably don't |
197
|
|
|
|
|
|
|
need to construct this class yourself, since L does the 'heavy |
198
|
|
|
|
|
|
|
lifting' for you in that regards. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head1 METHODS |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
This class exposes the following public methods. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 default_config |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
Merges with the C initializer to provide configuration information for |
207
|
|
|
|
|
|
|
your application. For example: |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub default_config { |
210
|
|
|
|
|
|
|
( |
211
|
|
|
|
|
|
|
title => 'Bloggery', |
212
|
|
|
|
|
|
|
posts_dir => $FindBin::Bin.'/posts', |
213
|
|
|
|
|
|
|
); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Now, the C attribute of C<$self> will be set to a HashRef |
217
|
|
|
|
|
|
|
containing keys 'title' and 'posts_dir'. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
The keys from default_config are merged into any config supplied, so |
220
|
|
|
|
|
|
|
if you construct your application like: |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
MyWebSimpleApp::Web->new( |
223
|
|
|
|
|
|
|
config => { title => 'Spoon', environment => 'dev' } |
224
|
|
|
|
|
|
|
) |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
then C will contain: |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
{ |
229
|
|
|
|
|
|
|
title => 'Spoon', |
230
|
|
|
|
|
|
|
posts_dir => '/path/to/myapp/posts', |
231
|
|
|
|
|
|
|
environment => 'dev' |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head2 run_if_script |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
The run_if_script method is designed to be used at the end of the script |
237
|
|
|
|
|
|
|
or .pm file where your application class is defined - for example: |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
## my_web_simple_app.pl |
240
|
|
|
|
|
|
|
#!/usr/bin/env perl |
241
|
|
|
|
|
|
|
use Web::Simple 'HelloWorld'; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
{ |
244
|
|
|
|
|
|
|
package HelloWorld; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub dispatch_request { |
247
|
|
|
|
|
|
|
sub (GET) { |
248
|
|
|
|
|
|
|
[ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ] |
249
|
|
|
|
|
|
|
}, |
250
|
|
|
|
|
|
|
sub () { |
251
|
|
|
|
|
|
|
[ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ] |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
HelloWorld->run_if_script; |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
This returns a true value, so your file is now valid as a module - so |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
require 'my_web_simple_app.pl'; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
my $hw = HelloWorld->new; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
will work fine (and you can rename it to lib/HelloWorld.pm later to make it |
265
|
|
|
|
|
|
|
a real use-able module). |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
However, it detects if it's being run as a script (via testing $0) and if |
268
|
|
|
|
|
|
|
so attempts to do the right thing. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
If run under a CGI environment, your application will execute as a CGI. |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
If run under a FastCGI environment, your application will execute as a |
273
|
|
|
|
|
|
|
FastCGI process (this works both for dynamic shared-hosting-style FastCGI |
274
|
|
|
|
|
|
|
and for apache FastCgiServer style setups). |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
If run from the commandline with a URL path, it runs a GET request against |
277
|
|
|
|
|
|
|
that path - |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
$ perl -Ilib examples/hello-world/hello-world.cgi / |
280
|
|
|
|
|
|
|
200 OK |
281
|
|
|
|
|
|
|
Content-Type: text/plain |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Hello world! |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
You can also provide a method name - |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
$ perl -Ilib examples/hello-world/hello-world.cgi POST / |
288
|
|
|
|
|
|
|
405 Method Not Allowed |
289
|
|
|
|
|
|
|
Content-Type: text/plain |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
Method not allowed |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
For a POST or PUT request, pairs on the command line will be treated |
294
|
|
|
|
|
|
|
as form variables. For any request, pairs on the command line ending in : |
295
|
|
|
|
|
|
|
are treated as headers, and 'Content:' will set the request body - |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
$ ./myapp POST / Accept: text/html form_field_name form_field_value |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
$ ./myapp POST / Content-Type: text/json Content: '{ "json": "here" }' |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
The body of the response is sent to STDOUT and the headers to STDERR, so |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
$ ./myapp GET / >index.html |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
will generally do the right thing. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
To send basic authentication credentials, use user:pass@ syntax - |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$ ./myapp GET bob:secret@/protected/path |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Additionally, you can treat the file as though it were a standard PSGI |
312
|
|
|
|
|
|
|
application file (*.psgi). For example you can start up up with C |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
plackup my_web_simple_app.pl |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
or C |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
starman my_web_simple_app.pl |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head2 to_psgi_app |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
This method is called by L to create the L app coderef |
323
|
|
|
|
|
|
|
for use via L and L. If you want to globally add middleware, |
324
|
|
|
|
|
|
|
you can override this method: |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
use Web::Simple 'HelloWorld'; |
327
|
|
|
|
|
|
|
use Plack::Builder; |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
{ |
330
|
|
|
|
|
|
|
package HelloWorld; |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
around 'to_psgi_app', sub { |
334
|
|
|
|
|
|
|
my ($orig, $self) = (shift, shift); |
335
|
|
|
|
|
|
|
my $app = $self->$orig(@_); |
336
|
|
|
|
|
|
|
builder { |
337
|
|
|
|
|
|
|
enable ...; ## whatever middleware you want |
338
|
|
|
|
|
|
|
$app; |
339
|
|
|
|
|
|
|
}; |
340
|
|
|
|
|
|
|
}; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
This method can also be used to mount a Web::Simple application within |
344
|
|
|
|
|
|
|
a separate C<*.psgi> file - |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
use strictures 1; |
347
|
|
|
|
|
|
|
use Plack::Builder; |
348
|
|
|
|
|
|
|
use WSApp; |
349
|
|
|
|
|
|
|
use AnotherWSApp; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
builder { |
352
|
|
|
|
|
|
|
mount '/' => WSApp->to_psgi_app; |
353
|
|
|
|
|
|
|
mount '/another' => AnotherWSApp->to_psgi_app; |
354
|
|
|
|
|
|
|
}; |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
This method can be called as a class method, in which case it implicitly |
357
|
|
|
|
|
|
|
calls ->new, or as an object method ... in which case it doesn't. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head2 run |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Used for running your application under stand-alone CGI and FCGI modes. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
I should document this more extensively but run_if_script will call it when |
364
|
|
|
|
|
|
|
you need it, so don't worry about it too much. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=head2 run_test_request |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
my $res = $app->run_test_request(GET => '/' => %headers); |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $res = $app->run_test_request(POST => '/' => %headers_or_form); |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
my $res = $app->run_test_request($http_request); |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
Accepts either an L object or ($method, $path) and runs that |
375
|
|
|
|
|
|
|
request against the application, returning an L object. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
If the HTTP method is POST or PUT, then a series of pairs can be passed after |
378
|
|
|
|
|
|
|
this to create a form style message body. If you need to test an upload, then |
379
|
|
|
|
|
|
|
create an L object by hand or use the C subroutine |
380
|
|
|
|
|
|
|
provided by L. |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
If you prefix the URL with 'user:pass@' this will be converted into |
383
|
|
|
|
|
|
|
an Authorization header for HTTP basic auth: |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
my $res = $app->run_test_request( |
386
|
|
|
|
|
|
|
GET => 'bob:secret@/protected/resource' |
387
|
|
|
|
|
|
|
); |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
If pairs are passed where the key ends in :, it is instead treated as a |
390
|
|
|
|
|
|
|
headers, so: |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
my $res = $app->run_test_request( |
393
|
|
|
|
|
|
|
POST => '/', |
394
|
|
|
|
|
|
|
'Accept:' => 'text/html', |
395
|
|
|
|
|
|
|
some_form_key => 'value' |
396
|
|
|
|
|
|
|
); |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
will do what you expect. You can also pass a special key of Content: to |
399
|
|
|
|
|
|
|
set the request body: |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
my $res = $app->run_test_request( |
402
|
|
|
|
|
|
|
POST => '/', |
403
|
|
|
|
|
|
|
'Content-Type:' => 'text/json', |
404
|
|
|
|
|
|
|
'Content:' => '{ "json": "here" }', |
405
|
|
|
|
|
|
|
); |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=head1 AUTHORS |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
See L for authors. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
See L for the copyright and license. |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=cut |