line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dancer::Request; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:SUKRIA'; |
3
|
|
|
|
|
|
|
#ABSTRACT: interface for accessing incoming requests |
4
|
|
|
|
|
|
|
$Dancer::Request::VERSION = '1.3514_04'; # TRIAL |
5
|
|
|
|
|
|
|
$Dancer::Request::VERSION = '1.351404'; |
6
|
183
|
|
|
183
|
|
765377
|
use strict; |
|
183
|
|
|
|
|
409
|
|
|
183
|
|
|
|
|
4354
|
|
7
|
183
|
|
|
183
|
|
775
|
use warnings; |
|
183
|
|
|
|
|
309
|
|
|
183
|
|
|
|
|
3703
|
|
8
|
183
|
|
|
183
|
|
754
|
use Carp; |
|
183
|
|
|
|
|
304
|
|
|
183
|
|
|
|
|
8789
|
|
9
|
|
|
|
|
|
|
|
10
|
183
|
|
|
183
|
|
1132
|
use base 'Dancer::Object'; |
|
183
|
|
|
|
|
417
|
|
|
183
|
|
|
|
|
22123
|
|
11
|
|
|
|
|
|
|
|
12
|
183
|
|
|
183
|
|
7658
|
use Dancer::Config 'setting'; |
|
183
|
|
|
|
|
368
|
|
|
183
|
|
|
|
|
7582
|
|
13
|
183
|
|
|
183
|
|
67716
|
use Dancer::Request::Upload; |
|
183
|
|
|
|
|
417
|
|
|
183
|
|
|
|
|
3792
|
|
14
|
183
|
|
|
183
|
|
61142
|
use Dancer::SharedData; |
|
183
|
|
|
|
|
473
|
|
|
183
|
|
|
|
|
4921
|
|
15
|
183
|
|
|
183
|
|
68391
|
use Dancer::Session; |
|
183
|
|
|
|
|
439
|
|
|
183
|
|
|
|
|
5455
|
|
16
|
183
|
|
|
183
|
|
1047
|
use Dancer::Exception qw(:all); |
|
183
|
|
|
|
|
381
|
|
|
183
|
|
|
|
|
20157
|
|
17
|
183
|
|
|
183
|
|
1066
|
use Encode; |
|
183
|
|
|
|
|
349
|
|
|
183
|
|
|
|
|
11533
|
|
18
|
183
|
|
|
183
|
|
74832
|
use HTTP::Body; |
|
183
|
|
|
|
|
2879367
|
|
|
183
|
|
|
|
|
5302
|
|
19
|
183
|
|
|
183
|
|
1307
|
use URI; |
|
183
|
|
|
|
|
375
|
|
|
183
|
|
|
|
|
4297
|
|
20
|
183
|
|
|
183
|
|
877
|
use URI::Escape; |
|
183
|
|
|
|
|
365
|
|
|
183
|
|
|
|
|
262025
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my @http_env_keys = ( |
23
|
|
|
|
|
|
|
'user_agent', 'accept_language', 'accept_charset', |
24
|
|
|
|
|
|
|
'accept_encoding', 'keep_alive', 'connection', 'accept', |
25
|
|
|
|
|
|
|
'accept_type', 'referer', #'host', managed manually |
26
|
|
|
|
|
|
|
); |
27
|
|
|
|
|
|
|
my $count = 0; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
__PACKAGE__->attributes( |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# query |
32
|
|
|
|
|
|
|
'env', 'path', 'method', |
33
|
|
|
|
|
|
|
'content_type', 'content_length', |
34
|
|
|
|
|
|
|
'id', |
35
|
|
|
|
|
|
|
'uploads', 'headers', 'path_info', |
36
|
|
|
|
|
|
|
'ajax', 'is_forward', |
37
|
|
|
|
|
|
|
@http_env_keys, |
38
|
|
|
|
|
|
|
); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub new { |
41
|
614
|
|
|
614
|
1
|
65980
|
my ($self, @args) = @_; |
42
|
614
|
50
|
|
|
|
1818
|
if (@args == 1) { |
43
|
0
|
|
|
|
|
0
|
@args = ('env' => $args[0]); |
44
|
0
|
|
|
|
|
0
|
Dancer::Deprecation->deprecated( |
45
|
|
|
|
|
|
|
fatal => 1, |
46
|
|
|
|
|
|
|
feature => 'Calling Dancer::Request->new($env)', |
47
|
|
|
|
|
|
|
version => 1.3059, |
48
|
|
|
|
|
|
|
reason => 'Please use Dancer::Request->new( env => $env ) instead', |
49
|
|
|
|
|
|
|
); |
50
|
|
|
|
|
|
|
} |
51
|
614
|
|
|
|
|
2838
|
$self->SUPER::new(@args); |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# aliases |
55
|
1
|
|
|
1
|
1
|
4
|
sub agent { $_[0]->user_agent } |
56
|
19
|
|
|
19
|
1
|
40
|
sub remote_address { $_[0]->address } |
57
|
1
|
50
|
|
1
|
1
|
4
|
sub forwarded_for_address { $_[0]->env->{'X_FORWARDED_FOR'} || $_[0]->env->{'HTTP_X_FORWARDED_FOR'} } |
58
|
|
|
|
|
|
|
sub address { |
59
|
|
|
|
|
|
|
setting('behind_proxy') |
60
|
|
|
|
|
|
|
? $_[0]->forwarded_for_address() |
61
|
|
|
|
|
|
|
: $_[0]->env->{REMOTE_ADDR} |
62
|
19
|
50
|
|
19
|
1
|
46
|
} |
63
|
|
|
|
|
|
|
sub host { |
64
|
34
|
50
|
|
34
|
1
|
83
|
if (@_==2) { |
65
|
0
|
|
|
|
|
0
|
$_[0]->{host} = $_[1]; |
66
|
|
|
|
|
|
|
} else { |
67
|
34
|
|
|
|
|
43
|
my $host; |
68
|
34
|
100
|
33
|
|
|
88
|
$host = ($_[0]->env->{X_FORWARDED_HOST} || $_[0]->env->{HTTP_X_FORWARDED_HOST}) if setting('behind_proxy'); |
69
|
34
|
100
|
100
|
|
|
180
|
$host || $_[0]->{host} || $_[0]->env->{HTTP_HOST}; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
0
|
|
|
0
|
1
|
0
|
sub remote_host { $_[0]->env->{REMOTE_HOST} } |
73
|
1
|
|
|
1
|
1
|
5
|
sub protocol { $_[0]->env->{SERVER_PROTOCOL} } |
74
|
1
|
|
|
1
|
1
|
5
|
sub port { $_[0]->env->{SERVER_PORT} } |
75
|
620
|
|
|
620
|
1
|
1713
|
sub request_uri { $_[0]->env->{REQUEST_URI} } |
76
|
1
|
|
|
1
|
1
|
3
|
sub user { $_[0]->env->{REMOTE_USER} } |
77
|
625
|
|
|
625
|
1
|
1378
|
sub script_name { $_[0]->env->{SCRIPT_NAME} } |
78
|
1
|
50
|
|
1
|
1
|
4
|
sub request_base { $_[0]->env->{REQUEST_BASE} || $_[0]->env->{HTTP_REQUEST_BASE} } |
79
|
|
|
|
|
|
|
sub scheme { |
80
|
33
|
|
|
33
|
1
|
41
|
my $scheme; |
81
|
33
|
100
|
|
|
|
64
|
if (setting('behind_proxy')) { |
82
|
|
|
|
|
|
|
# PSGI specs say that X_FORWARDED_PROTO will |
83
|
|
|
|
|
|
|
# be converted into HTTP_X_FORWARDED_PROTO |
84
|
|
|
|
|
|
|
# but Dancer::Test doesn't use PSGI (for now) |
85
|
|
|
|
|
|
|
$scheme = $_[0]->env->{'HTTP_X_FORWARDED_PROTO'} |
86
|
|
|
|
|
|
|
|| $_[0]->env->{'X_FORWARDED_PROTOCOL'} |
87
|
|
|
|
|
|
|
|| $_[0]->env->{'HTTP_X_FORWARDED_PROTOCOL'} |
88
|
|
|
|
|
|
|
|| $_[0]->env->{'HTTP_FORWARDED_PROTO'} |
89
|
5
|
|
100
|
|
|
10
|
|| $_[0]->env->{'X_FORWARDED_PROTO'} |
90
|
|
|
|
|
|
|
|| "" |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
return $scheme |
93
|
|
|
|
|
|
|
|| $_[0]->env->{'psgi.url_scheme'} |
94
|
33
|
|
50
|
|
|
113
|
|| $_[0]->env->{'PSGI.URL_SCHEME'} |
95
|
|
|
|
|
|
|
|| ""; |
96
|
|
|
|
|
|
|
} |
97
|
1
|
|
|
1
|
1
|
5
|
sub secure { $_[0]->scheme eq 'https' } |
98
|
3
|
|
|
3
|
1
|
9
|
sub uri { $_[0]->request_uri } |
99
|
|
|
|
|
|
|
|
100
|
18
|
|
|
18
|
1
|
58
|
sub is_head { $_[0]->{method} eq 'HEAD' } |
101
|
10
|
|
|
10
|
1
|
70
|
sub is_post { $_[0]->{method} eq 'POST' } |
102
|
2
|
|
|
2
|
1
|
8
|
sub is_get { $_[0]->{method} eq 'GET' } |
103
|
15
|
|
|
15
|
1
|
76
|
sub is_put { $_[0]->{method} eq 'PUT' } |
104
|
2
|
|
|
2
|
1
|
10
|
sub is_delete { $_[0]->{method} eq 'DELETE' } |
105
|
1
|
|
|
1
|
1
|
6
|
sub is_patch { $_[0]->{method} eq 'PATCH' } |
106
|
7
|
|
|
7
|
1
|
30
|
sub header { $_[0]->{headers}->header($_[1]) } |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# We used to store the whole raw unparsed body; this was a big problem for large |
109
|
|
|
|
|
|
|
# file uploads (Issue 1129). |
110
|
|
|
|
|
|
|
# The original fix was to stop doing so, and replace the accessor with one that |
111
|
|
|
|
|
|
|
# would read it out of the temp file returned by HTTP::Body->body - but that |
112
|
|
|
|
|
|
|
# doesn't work for e.g. parsed form submissions, only certain types. |
113
|
|
|
|
|
|
|
# So, back to the older way - we may have a request body squirreled away |
114
|
|
|
|
|
|
|
# in memory if the config included the raw_request_body_in_ram boolean |
115
|
17
|
|
|
17
|
1
|
82
|
sub body { $_[0]->{body} } |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# public interface compat with CGI.pm objects |
118
|
1
|
|
|
1
|
1
|
6
|
sub request_method { method(@_) } |
119
|
2
|
|
|
2
|
1
|
5
|
sub Vars { params(@_) } |
120
|
618
|
100
|
|
618
|
1
|
1391
|
sub input_handle { $_[0]->env->{'psgi.input'} || $_[0]->env->{'PSGI.INPUT'} } |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub init { |
123
|
614
|
|
|
614
|
1
|
1707
|
my ($self) = @_; |
124
|
|
|
|
|
|
|
|
125
|
614
|
|
50
|
|
|
2207
|
$self->{env} ||= {}; |
126
|
614
|
|
|
|
|
1459
|
$self->{path} = undef; |
127
|
614
|
|
|
|
|
1652
|
$self->{method} = undef; |
128
|
614
|
|
|
|
|
1716
|
$self->{params} = {}; |
129
|
614
|
|
100
|
|
|
3665
|
$self->{is_forward} ||= 0; |
130
|
614
|
|
100
|
|
|
2015
|
$self->{content_length} = $self->env->{CONTENT_LENGTH} || 0; |
131
|
614
|
|
100
|
|
|
1987
|
$self->{content_type} = $self->env->{CONTENT_TYPE} || ''; |
132
|
614
|
|
|
|
|
2217
|
$self->{id} = ++$count; |
133
|
614
|
|
|
|
|
1553
|
$self->{_chunk_size} = 4096; |
134
|
614
|
|
|
|
|
1754
|
$self->{_read_position} = 0; |
135
|
614
|
|
|
|
|
1576
|
$self->{_body_params} = undef; |
136
|
614
|
|
|
|
|
1642
|
$self->{_query_params} = undef; |
137
|
614
|
|
|
|
|
1613
|
$self->{_route_params} = {}; |
138
|
|
|
|
|
|
|
|
139
|
614
|
|
|
|
|
1918
|
$self->_build_headers(); |
140
|
614
|
|
|
|
|
2019
|
$self->_build_request_env(); |
141
|
614
|
50
|
|
|
|
1584
|
$self->_build_path() unless $self->path; |
142
|
614
|
50
|
|
|
|
1490
|
$self->_build_path_info() unless $self->path_info; |
143
|
614
|
50
|
|
|
|
1489
|
$self->_build_method() unless $self->method; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
$self->{_http_body} |
146
|
614
|
|
|
|
|
1586
|
= HTTP::Body->new($self->content_type, $self->content_length); |
147
|
614
|
|
|
|
|
41433
|
$self->{_http_body}->cleanup(1); |
148
|
614
|
|
|
|
|
3794
|
$self->{body} = ''; # default, because we might not store it now. |
149
|
614
|
|
|
|
|
1568
|
$self->_build_params(); |
150
|
614
|
50
|
|
|
|
1864
|
$self->_build_uploads unless $self->uploads; |
151
|
614
|
|
|
|
|
1668
|
$self->{ajax} = $self->is_ajax; |
152
|
|
|
|
|
|
|
|
153
|
614
|
|
|
|
|
1256
|
return $self; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub to_string { |
157
|
1
|
|
|
1
|
1
|
4
|
my ($self) = @_; |
158
|
1
|
|
|
|
|
3
|
return "[#" . $self->id . "] " . $self->method . " " . $self->path; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# helper for building a request object by hand |
162
|
|
|
|
|
|
|
# with the given method, path, params, body and headers. |
163
|
|
|
|
|
|
|
sub new_for_request { |
164
|
574
|
|
|
574
|
1
|
3298
|
my ($class, $method, $uri, $params, $body, $headers, $extra_env) = @_; |
165
|
574
|
|
100
|
|
|
2705
|
$params ||= {}; |
166
|
574
|
|
100
|
|
|
1695
|
$extra_env ||= {}; |
167
|
574
|
|
|
|
|
1256
|
$method = uc($method); |
168
|
|
|
|
|
|
|
|
169
|
574
|
|
|
|
|
3281
|
my ( $path, $query_string ) = ( $uri =~ /([^?]*)(?:\?(.*))?/s ); #from HTTP::Server::Simple |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $env = { |
172
|
|
|
|
|
|
|
%ENV, |
173
|
574
|
|
|
|
|
15331
|
%{$extra_env}, |
174
|
|
|
|
|
|
|
PATH_INFO => $path, |
175
|
574
|
|
100
|
|
|
4812
|
QUERY_STRING => $query_string || $ENV{QUERY_STRING} || '', |
176
|
|
|
|
|
|
|
REQUEST_METHOD => $method |
177
|
|
|
|
|
|
|
}; |
178
|
574
|
100
|
|
|
|
3447
|
$env->{CONTENT_LENGTH} = defined($body) ? length($body) : 0 if !exists $env->{CONTENT_LENGTH}; |
|
|
100
|
|
|
|
|
|
179
|
574
|
|
|
|
|
2397
|
my $req = $class->new(env => $env); |
180
|
574
|
|
|
|
|
828
|
$req->{params} = {%{$req->{params}}, %{$params}}; |
|
574
|
|
|
|
|
1087
|
|
|
574
|
|
|
|
|
1116
|
|
181
|
574
|
|
|
|
|
1420
|
$req->_build_params(); |
182
|
574
|
|
|
|
|
1023
|
$req->{_query_params} = $req->{params}; |
183
|
574
|
|
|
|
|
1718
|
my $store_raw_body = setting('raw_request_body_in_ram'); |
184
|
574
|
50
|
|
|
|
1233
|
$store_raw_body = defined $store_raw_body ? $store_raw_body : 1; |
185
|
574
|
50
|
|
|
|
1163
|
if ($store_raw_body) { |
186
|
574
|
|
|
|
|
913
|
$req->{body} = $body; |
187
|
|
|
|
|
|
|
} |
188
|
574
|
|
66
|
|
|
1535
|
$req->{headers} = $headers || HTTP::Headers->new; |
189
|
|
|
|
|
|
|
|
190
|
574
|
|
|
|
|
2226
|
return $req; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
#Create a new request which is a clone of the current one, apart |
194
|
|
|
|
|
|
|
#from the path location, which points instead to the new location |
195
|
|
|
|
|
|
|
sub forward { |
196
|
16
|
|
|
16
|
1
|
28
|
my ($class, $request, $to_data) = @_; |
197
|
|
|
|
|
|
|
|
198
|
16
|
|
|
|
|
35
|
my $env = $request->env; |
199
|
16
|
|
|
|
|
29
|
$env->{PATH_INFO} = $to_data->{to_url}; |
200
|
|
|
|
|
|
|
|
201
|
16
|
|
|
|
|
33
|
my $new_request = $class->new(env => $env, is_forward => 1); |
202
|
|
|
|
|
|
|
my $new_params = _merge_params(scalar($request->params), |
203
|
16
|
|
100
|
|
|
31
|
$to_data->{params} || {}); |
204
|
|
|
|
|
|
|
|
205
|
16
|
100
|
|
|
|
34
|
if (exists($to_data->{options}{method})) { |
206
|
2
|
50
|
|
|
|
4
|
die unless _valid_method($to_data->{options}{method}); |
207
|
2
|
|
|
|
|
4
|
$new_request->{method} = uc $to_data->{options}{method}; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
16
|
|
|
|
|
21
|
$new_request->{params} = $new_params; |
211
|
16
|
|
|
|
|
24
|
$new_request->{_body_params} = $request->{_body_params}; |
212
|
16
|
|
|
|
|
20
|
$new_request->{_query_params} = $request->{_query_params}; |
213
|
16
|
|
|
|
|
20
|
$new_request->{_route_params} = $request->{_route_params}; |
214
|
16
|
|
|
|
|
19
|
$new_request->{_params_are_decoded} = 1; |
215
|
16
|
|
|
|
|
35
|
$new_request->{headers} = $request->headers; |
216
|
|
|
|
|
|
|
|
217
|
16
|
100
|
66
|
|
|
53
|
if( my $session = Dancer::Session->engine |
218
|
|
|
|
|
|
|
&& Dancer::Session->get_current_session ) { |
219
|
15
|
|
|
|
|
25
|
my $name = $session->session_name; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# make sure that COOKIE is populated |
222
|
15
|
|
33
|
|
|
56
|
$new_request->{env}{COOKIE} ||= $new_request->{env}{HTTP_COOKIE}; |
223
|
|
|
|
|
|
|
|
224
|
183
|
|
|
183
|
|
1481
|
no warnings; # COOKIE can be undef |
|
183
|
|
|
|
|
456
|
|
|
183
|
|
|
|
|
426402
|
|
225
|
15
|
50
|
|
|
|
74
|
unless ( $new_request->{env}{COOKIE} =~ /$name\s*=/ ) { |
226
|
|
|
|
|
|
|
$new_request->{env}{COOKIE} = join ';', |
227
|
30
|
|
|
|
|
58
|
grep { $_ } |
228
|
|
|
|
|
|
|
$new_request->{env}{COOKIE}, |
229
|
15
|
|
|
|
|
36
|
join '=', $name, Dancer::Session->get_current_session->id; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
16
|
|
|
|
|
34
|
$new_request->{uploads} = $request->uploads; |
234
|
|
|
|
|
|
|
|
235
|
16
|
|
|
|
|
45
|
return $new_request; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub _valid_method { |
239
|
2
|
|
|
2
|
|
3
|
my $method = shift; |
240
|
2
|
|
|
|
|
12
|
return $method =~ /^(?:head|post|get|put|delete)$/i; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _merge_params { |
244
|
16
|
|
|
16
|
|
26
|
my ($params, $to_add) = @_; |
245
|
|
|
|
|
|
|
|
246
|
16
|
50
|
|
|
|
29
|
die unless ref $to_add eq "HASH"; |
247
|
16
|
|
|
|
|
32
|
for my $key (keys %$to_add) { |
248
|
4
|
|
|
|
|
7
|
$params->{$key} = $to_add->{$key}; |
249
|
|
|
|
|
|
|
} |
250
|
16
|
|
|
|
|
21
|
return $params; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub base { |
254
|
29
|
|
|
29
|
1
|
1334
|
my $self = shift; |
255
|
29
|
|
|
|
|
55
|
my $uri = $self->_common_uri; |
256
|
|
|
|
|
|
|
|
257
|
29
|
|
|
|
|
95
|
return $uri->canonical; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub _common_uri { |
261
|
32
|
|
|
32
|
|
43
|
my $self = shift; |
262
|
|
|
|
|
|
|
|
263
|
32
|
|
100
|
|
|
66
|
my $path = $self->env->{SCRIPT_NAME} || ''; |
264
|
32
|
|
|
|
|
59
|
my $port = $self->env->{SERVER_PORT}; |
265
|
32
|
|
|
|
|
67
|
my $server = $self->env->{SERVER_NAME}; |
266
|
32
|
|
|
|
|
91
|
my $host = $self->host; |
267
|
32
|
|
|
|
|
72
|
my $scheme = $self->scheme; |
268
|
|
|
|
|
|
|
|
269
|
32
|
|
|
|
|
120
|
my $uri = URI->new; |
270
|
32
|
|
|
|
|
33345
|
$uri->scheme($scheme); |
271
|
32
|
|
66
|
|
|
28357
|
$uri->authority($host || "$server:$port"); |
272
|
32
|
100
|
|
|
|
1278
|
if (setting('behind_proxy')) { |
273
|
5
|
|
100
|
|
|
12
|
my $request_base = $self->env->{REQUEST_BASE} || $self->env->{HTTP_REQUEST_BASE} || ''; |
274
|
5
|
|
100
|
|
|
26
|
$uri->path($request_base . $path || '/'); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
else { |
277
|
27
|
|
100
|
|
|
135
|
$uri->path($path || '/'); |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
32
|
|
|
|
|
1002
|
return $uri; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub uri_base { |
284
|
3
|
|
|
3
|
1
|
22
|
my $self = shift; |
285
|
3
|
|
|
|
|
7
|
my $uri = $self->_common_uri; |
286
|
3
|
|
|
|
|
8
|
my $canon = $uri->canonical; |
287
|
|
|
|
|
|
|
|
288
|
3
|
100
|
|
|
|
320
|
if ( $uri->path eq '/' ) { |
289
|
2
|
|
|
|
|
23
|
$canon =~ s{/$}{}; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
3
|
|
|
|
|
76
|
return $canon; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub uri_for { |
296
|
26
|
|
|
26
|
1
|
5817
|
my ($self, $part, $params, $dont_escape) = @_; |
297
|
26
|
|
|
|
|
58
|
my $uri = $self->base; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# Make sure there's exactly one slash between the base and the new part |
300
|
26
|
|
|
|
|
2296
|
my $base = $uri->path; |
301
|
26
|
|
|
|
|
240
|
$base =~ s|/$||; |
302
|
26
|
|
|
|
|
65
|
$part =~ s|^/||; |
303
|
26
|
|
|
|
|
96
|
$uri->path("$base/$part"); |
304
|
|
|
|
|
|
|
|
305
|
26
|
100
|
|
|
|
722
|
$uri->query_form($params) if $params; |
306
|
|
|
|
|
|
|
|
307
|
26
|
100
|
|
|
|
868
|
return $dont_escape ? uri_unescape($uri->canonical) : $uri->canonical; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub params { |
311
|
436
|
|
|
436
|
1
|
1443
|
my ($self, $source) = @_; |
312
|
|
|
|
|
|
|
|
313
|
436
|
|
|
|
|
1375
|
my @caller = caller; |
314
|
|
|
|
|
|
|
|
315
|
436
|
100
|
|
|
|
1129
|
if (not $self->{_params_are_decoded}) { |
316
|
289
|
|
|
|
|
667
|
$self->{params} = _decode($self->{params}); |
317
|
289
|
|
|
|
|
624
|
$self->{_body_params} = _decode($self->{_body_params}); |
318
|
289
|
|
|
|
|
609
|
$self->{_query_params} = _decode($self->{_query_params}); |
319
|
289
|
|
|
|
|
566
|
$self->{_route_params} = _decode($self->{_route_params}); |
320
|
289
|
|
|
|
|
1217
|
$self->{_params_are_decoded} = 1; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
436
|
100
|
100
|
|
|
1108
|
return %{$self->{params}} if wantarray && @_ == 1; |
|
15
|
|
|
|
|
79
|
|
324
|
421
|
100
|
|
|
|
1928
|
return $self->{params} if @_ == 1; |
325
|
|
|
|
|
|
|
|
326
|
19
|
100
|
|
|
|
113
|
if ($source eq 'query') { |
|
|
50
|
|
|
|
|
|
327
|
4
|
100
|
|
|
|
11
|
return %{$self->{_query_params}} if wantarray; |
|
2
|
|
|
|
|
14
|
|
328
|
2
|
|
|
|
|
8
|
return $self->{_query_params}; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
elsif ($source eq 'body') { |
331
|
15
|
50
|
|
|
|
58
|
return %{$self->{_body_params}} if wantarray; |
|
0
|
|
|
|
|
0
|
|
332
|
15
|
|
|
|
|
57
|
return $self->{_body_params}; |
333
|
|
|
|
|
|
|
} |
334
|
0
|
0
|
|
|
|
0
|
if ($source eq 'route') { |
335
|
0
|
0
|
|
|
|
0
|
return %{$self->{_route_params}} if wantarray; |
|
0
|
|
|
|
|
0
|
|
336
|
0
|
|
|
|
|
0
|
return $self->{_route_params}; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
else { |
339
|
0
|
|
|
|
|
0
|
raise core_request => "Unknown source params \"$source\"."; |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub _decode { |
344
|
2541
|
|
|
2541
|
|
6540
|
my ($h) = @_; |
345
|
2541
|
100
|
|
|
|
4002
|
return if not defined $h; |
346
|
|
|
|
|
|
|
|
347
|
2529
|
100
|
100
|
|
|
5340
|
if (!ref($h) && !utf8::is_utf8($h)) { |
348
|
622
|
|
|
|
|
2424
|
return decode('UTF-8', $h); |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
1907
|
100
|
|
|
|
3415
|
if (ref($h) eq 'HASH') { |
352
|
1796
|
|
|
|
|
4448
|
while (my ($k, $v) = each(%$h)) { |
353
|
631
|
|
|
|
|
7413
|
$h->{$k} = _decode($v); |
354
|
|
|
|
|
|
|
} |
355
|
1796
|
|
|
|
|
18955
|
return $h; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
111
|
100
|
|
|
|
205
|
if (ref($h) eq 'ARRAY') { |
359
|
83
|
|
|
|
|
136
|
return [ map { _decode($_) } @$h ]; |
|
140
|
|
|
|
|
2317
|
|
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
28
|
|
|
|
|
84
|
return $h; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub is_ajax { |
366
|
617
|
|
|
617
|
1
|
1013
|
my $self = shift; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# when using Plack::Builder headers are not set |
369
|
|
|
|
|
|
|
# so we're checking if it's actually there with PSGI plain headers |
370
|
617
|
50
|
|
|
|
1511
|
if ( defined $self->{x_requested_with} ) { |
371
|
0
|
0
|
|
|
|
0
|
if ( $self->{x_requested_with} eq "XMLHttpRequest" ) { |
372
|
0
|
|
|
|
|
0
|
return 1; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
617
|
100
|
|
|
|
1423
|
return 0 unless defined $self->headers; |
377
|
4
|
100
|
|
|
|
11
|
return 0 unless defined $self->header('X-Requested-With'); |
378
|
1
|
50
|
|
|
|
33
|
return 0 if $self->header('X-Requested-With') ne 'XMLHttpRequest'; |
379
|
1
|
|
|
|
|
29
|
return 1; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# context-aware accessor for uploads |
383
|
|
|
|
|
|
|
sub upload { |
384
|
8
|
|
|
8
|
1
|
1308
|
my ($self, $name) = @_; |
385
|
8
|
|
|
|
|
24
|
my $res = $self->{uploads}{$name}; |
386
|
|
|
|
|
|
|
|
387
|
8
|
100
|
|
|
|
36
|
return $res unless wantarray; |
388
|
3
|
100
|
|
|
|
12
|
return () unless defined $res; |
389
|
2
|
100
|
|
|
|
297
|
return (ref($res) eq 'ARRAY') ? @$res : $res; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# Some Dancer's core components sometimes need to alter |
393
|
|
|
|
|
|
|
# the parsed request params, these protected accessors are provided |
394
|
|
|
|
|
|
|
# for this purpose |
395
|
|
|
|
|
|
|
sub _set_route_params { |
396
|
652
|
|
|
652
|
|
1160
|
my ($self, $params) = @_; |
397
|
652
|
|
|
|
|
1227
|
$self->{_route_params} = $params; |
398
|
652
|
|
|
|
|
1273
|
$self->_build_params(); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub _set_body_params { |
402
|
8
|
|
|
8
|
|
21
|
my ($self, $params) = @_; |
403
|
8
|
|
|
|
|
16
|
$self->{_body_params} = $params; |
404
|
8
|
|
|
|
|
19
|
$self->_build_params(); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub _set_query_params { |
408
|
0
|
|
|
0
|
|
0
|
my ($self, $params) = @_; |
409
|
0
|
|
|
|
|
0
|
$self->{_query_params} = $params; |
410
|
0
|
|
|
|
|
0
|
$self->_build_params(); |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub _build_request_env { |
414
|
614
|
|
|
614
|
|
1157
|
my ($self) = @_; |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
# Don't refactor that, it's called whenever a request object is needed, that |
417
|
|
|
|
|
|
|
# means at least once per request. If refactored in a loop, this will cost 4 |
418
|
|
|
|
|
|
|
# times more than the following static map. |
419
|
614
|
|
|
|
|
1443
|
my $env = $self->env; |
420
|
614
|
|
|
|
|
1534
|
$self->{user_agent} = $env->{HTTP_USER_AGENT}; |
421
|
614
|
|
|
|
|
1695
|
$self->{host} = $env->{HTTP_HOST}; |
422
|
614
|
|
|
|
|
1545
|
$self->{accept_language} = $env->{HTTP_ACCEPT_LANGUAGE}; |
423
|
614
|
|
|
|
|
1107
|
$self->{accept_charset} = $env->{HTTP_ACCEPT_CHARSET}; |
424
|
614
|
|
|
|
|
1132
|
$self->{accept_encoding} = $env->{HTTP_ACCEPT_ENCODING}; |
425
|
614
|
|
|
|
|
964
|
$self->{keep_alive} = $env->{HTTP_KEEP_ALIVE}; |
426
|
614
|
|
|
|
|
1547
|
$self->{connection} = $env->{HTTP_CONNECTION}; |
427
|
614
|
|
|
|
|
1046
|
$self->{accept} = $env->{HTTP_ACCEPT}; |
428
|
614
|
|
|
|
|
1100
|
$self->{accept_type} = $env->{HTTP_ACCEPT_TYPE}; |
429
|
614
|
|
|
|
|
1106
|
$self->{referer} = $env->{HTTP_REFERER}; |
430
|
614
|
|
|
|
|
1483
|
$self->{x_requested_with} = $env->{HTTP_X_REQUESTED_WITH}; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub _build_headers { |
434
|
614
|
|
|
614
|
|
1602
|
my ($self) = @_; |
435
|
614
|
|
|
|
|
2600
|
$self->{headers} = Dancer::SharedData->headers; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub _build_params { |
439
|
2462
|
|
|
2462
|
|
3429
|
my ($self) = @_; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# params may have been populated by before filters |
442
|
|
|
|
|
|
|
# _before_ we get there, so we have to save it first |
443
|
2462
|
|
|
|
|
3109
|
my $previous = $self->{params}; |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
# now parse environment params... |
446
|
2462
|
|
|
|
|
4881
|
$self->_parse_get_params(); |
447
|
2462
|
100
|
|
|
|
4389
|
if ($self->is_forward) { |
448
|
47
|
|
100
|
|
|
118
|
$self->{_body_params} ||= {}; |
449
|
|
|
|
|
|
|
} else { |
450
|
2415
|
|
|
|
|
3829
|
$self->_parse_post_params(); |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
# and merge everything |
454
|
|
|
|
|
|
|
$self->{params} = { |
455
|
2462
|
|
|
|
|
3509
|
%$previous, %{$self->{_query_params}}, |
456
|
2462
|
|
|
|
|
6755
|
%{$self->{_route_params}}, %{$self->{_body_params}}, |
|
2462
|
|
|
|
|
3567
|
|
|
2462
|
|
|
|
|
5565
|
|
457
|
|
|
|
|
|
|
}; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
# Written from PSGI specs: |
462
|
|
|
|
|
|
|
# http://search.cpan.org/dist/PSGI/PSGI.pod |
463
|
|
|
|
|
|
|
sub _build_path { |
464
|
614
|
|
|
614
|
|
1124
|
my ($self) = @_; |
465
|
614
|
|
|
|
|
1085
|
my $path = ""; |
466
|
|
|
|
|
|
|
|
467
|
614
|
100
|
|
|
|
1870
|
$path .= $self->script_name if defined $self->script_name; |
468
|
614
|
100
|
|
|
|
1499
|
$path .= $self->env->{PATH_INFO} if defined $self->env->{PATH_INFO}; |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
# fallback to REQUEST_URI if nothing found |
471
|
|
|
|
|
|
|
# we have to decode it, according to PSGI specs. |
472
|
614
|
100
|
|
|
|
1510
|
if (defined $self->request_uri) { |
473
|
529
|
|
33
|
|
|
1108
|
$path ||= $self->_url_decode($self->request_uri); |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
614
|
50
|
|
|
|
1256
|
raise core_request => "Cannot resolve path" if not $path; |
477
|
614
|
|
|
|
|
1278
|
$self->{path} = $path; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
sub _build_path_info { |
481
|
614
|
|
|
614
|
|
984
|
my ($self) = @_; |
482
|
614
|
|
|
|
|
1195
|
my $info = $self->env->{PATH_INFO}; |
483
|
614
|
100
|
|
|
|
1287
|
if (defined $info) { |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# Empty path info will be interpreted as "root". |
486
|
607
|
|
50
|
|
|
1272
|
$info ||= '/'; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
else { |
489
|
7
|
|
|
|
|
16
|
$info = $self->path; |
490
|
|
|
|
|
|
|
} |
491
|
614
|
|
|
|
|
1195
|
$self->{path_info} = $info; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub _build_method { |
495
|
614
|
|
|
614
|
|
1013
|
my ($self) = @_; |
496
|
|
|
|
|
|
|
$self->{method} = $self->env->{REQUEST_METHOD} |
497
|
614
|
|
33
|
|
|
1153
|
|| $self->{request}->request_method(); |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub _url_decode { |
501
|
80
|
|
|
80
|
|
114
|
my ($self, $encoded) = @_; |
502
|
80
|
|
|
|
|
94
|
my $clean = $encoded; |
503
|
80
|
|
|
|
|
100
|
$clean =~ tr/\+/ /; |
504
|
80
|
|
|
|
|
133
|
$clean =~ s/%([a-fA-F0-9]{2})/pack "H2", $1/eg; |
|
4
|
|
|
|
|
18
|
|
505
|
80
|
|
|
|
|
113
|
return $clean; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub _parse_post_params { |
509
|
2415
|
|
|
2415
|
|
3167
|
my ($self) = @_; |
510
|
2415
|
100
|
|
|
|
4583
|
return $self->{_body_params} if defined $self->{_body_params}; |
511
|
|
|
|
|
|
|
|
512
|
598
|
|
|
|
|
1460
|
$self->_read_to_end(); |
513
|
598
|
|
|
|
|
2110
|
$self->{_body_params} = $self->{_http_body}->param; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
sub _parse_get_params { |
517
|
2462
|
|
|
2462
|
|
3184
|
my ($self) = @_; |
518
|
2462
|
100
|
|
|
|
5104
|
return $self->{_query_params} if defined $self->{_query_params}; |
519
|
614
|
|
|
|
|
1066
|
$self->{_query_params} = {}; |
520
|
|
|
|
|
|
|
|
521
|
614
|
|
100
|
|
|
1395
|
my $source = $self->env->{QUERY_STRING} || ''; |
522
|
614
|
|
|
|
|
1921
|
foreach my $token (split /[&;]/, $source) { |
523
|
40
|
|
|
|
|
97
|
my ($key, $val) = split(/=/, $token, 2); |
524
|
40
|
50
|
|
|
|
80
|
next unless defined $key; |
525
|
40
|
50
|
|
|
|
66
|
$val = (defined $val) ? $val : ''; |
526
|
40
|
|
|
|
|
70
|
$key = $self->_url_decode($key); |
527
|
40
|
|
|
|
|
66
|
$val = $self->_url_decode($val); |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
# looking for multi-value params |
530
|
40
|
100
|
|
|
|
80
|
if (exists $self->{_query_params}{$key}) { |
531
|
4
|
|
|
|
|
7
|
my $prev_val = $self->{_query_params}{$key}; |
532
|
4
|
50
|
33
|
|
|
16
|
if (ref($prev_val) && ref($prev_val) eq 'ARRAY') { |
533
|
0
|
|
|
|
|
0
|
push @{$self->{_query_params}{$key}}, $val; |
|
0
|
|
|
|
|
0
|
|
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
else { |
536
|
4
|
|
|
|
|
13
|
$self->{_query_params}{$key} = [$prev_val, $val]; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# simple value param (first time we see it) |
541
|
|
|
|
|
|
|
else { |
542
|
36
|
|
|
|
|
75
|
$self->{_query_params}{$key} = $val; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
} |
545
|
614
|
|
|
|
|
998
|
return $self->{_query_params}; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub _read_to_end { |
549
|
598
|
|
|
598
|
|
921
|
my $self = shift; |
550
|
|
|
|
|
|
|
|
551
|
598
|
100
|
|
|
|
1235
|
return unless $self->_has_something_to_read; |
552
|
|
|
|
|
|
|
|
553
|
32
|
100
|
|
|
|
102
|
if ( $self->content_length > 0 ) { |
554
|
20
|
|
|
|
|
42
|
my $body = ''; |
555
|
|
|
|
|
|
|
|
556
|
20
|
|
|
|
|
88
|
my $store_raw_body = setting('raw_request_body_in_ram'); |
557
|
20
|
50
|
|
|
|
78
|
$store_raw_body = defined $store_raw_body ? $store_raw_body : 1; |
558
|
|
|
|
|
|
|
|
559
|
20
|
|
|
|
|
61
|
while ( my $buffer = $self->_read ) { |
560
|
20
|
|
|
|
|
123
|
$self->{_http_body}->add($buffer); |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# Only keep a copy of the raw request body in RAM if the user has |
563
|
|
|
|
|
|
|
# asked us to |
564
|
|
|
|
|
|
|
|
565
|
20
|
50
|
|
|
|
16168
|
if ($store_raw_body) { |
566
|
20
|
|
|
|
|
100
|
$self->{body} .= $buffer; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
32
|
|
|
|
|
66
|
return $self->{_http_body}; |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
sub _has_something_to_read { |
576
|
598
|
|
|
598
|
|
1639
|
defined $_[0]->input_handle; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# taken from Miyagawa's Plack::Request::BodyParser |
580
|
|
|
|
|
|
|
sub _read { |
581
|
40
|
|
|
40
|
|
83
|
my ($self,) = @_; |
582
|
40
|
|
|
|
|
108
|
my $remaining = $self->content_length - $self->{_read_position}; |
583
|
40
|
|
|
|
|
69
|
my $maxlength = $self->{_chunk_size}; |
584
|
|
|
|
|
|
|
|
585
|
40
|
100
|
|
|
|
146
|
return if ($remaining <= 0); |
586
|
|
|
|
|
|
|
|
587
|
20
|
50
|
|
|
|
53
|
my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining; |
588
|
20
|
|
|
|
|
37
|
my $buffer; |
589
|
|
|
|
|
|
|
my $rc; |
590
|
|
|
|
|
|
|
|
591
|
20
|
|
|
|
|
46
|
$rc = $self->input_handle->read($buffer, $readlen); |
592
|
|
|
|
|
|
|
|
593
|
20
|
50
|
|
|
|
236
|
if (defined $rc) { |
594
|
20
|
|
|
|
|
42
|
$self->{_read_position} += $rc; |
595
|
20
|
|
|
|
|
97
|
return $buffer; |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
else { |
598
|
0
|
|
|
|
|
0
|
raise core_request => "Unknown error reading input: $!"; |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
# Taken gently from Plack::Request, thanks to Plack authors. |
603
|
|
|
|
|
|
|
sub _build_uploads { |
604
|
614
|
|
|
614
|
|
1090
|
my ($self) = @_; |
605
|
|
|
|
|
|
|
|
606
|
614
|
|
|
|
|
1948
|
my $uploads = _decode($self->{_http_body}->upload); |
607
|
614
|
|
|
|
|
1472
|
my %uploads; |
608
|
|
|
|
|
|
|
|
609
|
614
|
|
|
|
|
920
|
for my $name (keys %{$uploads}) { |
|
614
|
|
|
|
|
1293
|
|
610
|
9
|
|
|
|
|
17
|
my $files = $uploads->{$name}; |
611
|
9
|
100
|
|
|
|
39
|
$files = ref $files eq 'ARRAY' ? $files : [$files]; |
612
|
|
|
|
|
|
|
|
613
|
9
|
|
|
|
|
13
|
my @uploads; |
614
|
9
|
|
|
|
|
13
|
for my $upload (@{$files}) { |
|
9
|
|
|
|
|
18
|
|
615
|
|
|
|
|
|
|
push( |
616
|
|
|
|
|
|
|
@uploads, |
617
|
|
|
|
|
|
|
Dancer::Request::Upload->new( |
618
|
|
|
|
|
|
|
headers => $upload->{headers}, |
619
|
|
|
|
|
|
|
tempname => $upload->{tempname}, |
620
|
|
|
|
|
|
|
size => $upload->{size}, |
621
|
|
|
|
|
|
|
filename => $upload->{filename}, |
622
|
|
|
|
|
|
|
) |
623
|
11
|
|
|
|
|
150
|
); |
624
|
|
|
|
|
|
|
} |
625
|
9
|
100
|
|
|
|
31
|
$uploads{$name} = @uploads > 1 ? \@uploads : $uploads[0]; |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# support access to the filename as a normal param |
628
|
9
|
|
|
|
|
21
|
my @filenames = map { $_->{filename} } @uploads; |
|
11
|
|
|
|
|
36
|
|
629
|
9
|
100
|
|
|
|
38
|
$self->{_body_params}{$name} = |
630
|
|
|
|
|
|
|
@filenames > 1 ? \@filenames : $filenames[0]; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
614
|
|
|
|
|
1276
|
$self->{uploads} = \%uploads; |
634
|
614
|
|
|
|
|
1175
|
$self->_build_params(); |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
1; |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
__END__ |