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.3520'; |
5
|
182
|
|
|
182
|
|
921555
|
use strict; |
|
182
|
|
|
|
|
495
|
|
|
182
|
|
|
|
|
5311
|
|
6
|
182
|
|
|
182
|
|
929
|
use warnings; |
|
182
|
|
|
|
|
423
|
|
|
182
|
|
|
|
|
4285
|
|
7
|
182
|
|
|
182
|
|
936
|
use Carp; |
|
182
|
|
|
|
|
1490
|
|
|
182
|
|
|
|
|
10019
|
|
8
|
|
|
|
|
|
|
|
9
|
182
|
|
|
182
|
|
1183
|
use base 'Dancer::Object'; |
|
182
|
|
|
|
|
480
|
|
|
182
|
|
|
|
|
26540
|
|
10
|
|
|
|
|
|
|
|
11
|
182
|
|
|
182
|
|
8790
|
use Dancer::Config 'setting'; |
|
182
|
|
|
|
|
474
|
|
|
182
|
|
|
|
|
10280
|
|
12
|
182
|
|
|
182
|
|
82433
|
use Dancer::Request::Upload; |
|
182
|
|
|
|
|
469
|
|
|
182
|
|
|
|
|
4611
|
|
13
|
182
|
|
|
182
|
|
73515
|
use Dancer::SharedData; |
|
182
|
|
|
|
|
710
|
|
|
182
|
|
|
|
|
6081
|
|
14
|
182
|
|
|
182
|
|
81616
|
use Dancer::Session; |
|
182
|
|
|
|
|
591
|
|
|
182
|
|
|
|
|
6486
|
|
15
|
182
|
|
|
182
|
|
1278
|
use Dancer::Exception qw(:all); |
|
182
|
|
|
|
|
458
|
|
|
182
|
|
|
|
|
22949
|
|
16
|
182
|
|
|
182
|
|
1347
|
use Encode; |
|
182
|
|
|
|
|
651
|
|
|
182
|
|
|
|
|
15064
|
|
17
|
182
|
|
|
182
|
|
89594
|
use HTTP::Body; |
|
182
|
|
|
|
|
3622111
|
|
|
182
|
|
|
|
|
7069
|
|
18
|
182
|
|
|
182
|
|
1516
|
use URI; |
|
182
|
|
|
|
|
746
|
|
|
182
|
|
|
|
|
5123
|
|
19
|
182
|
|
|
182
|
|
1082
|
use URI::Escape; |
|
182
|
|
|
|
|
468
|
|
|
182
|
|
|
|
|
328228
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my @http_env_keys = ( |
22
|
|
|
|
|
|
|
'user_agent', 'accept_language', 'accept_charset', |
23
|
|
|
|
|
|
|
'accept_encoding', 'keep_alive', 'connection', 'accept', |
24
|
|
|
|
|
|
|
'accept_type', 'referer', #'host', managed manually |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
my $count = 0; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
__PACKAGE__->attributes( |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# query |
31
|
|
|
|
|
|
|
'env', 'path', 'method', |
32
|
|
|
|
|
|
|
'content_type', 'content_length', |
33
|
|
|
|
|
|
|
'id', |
34
|
|
|
|
|
|
|
'uploads', 'headers', 'path_info', |
35
|
|
|
|
|
|
|
'ajax', 'is_forward', |
36
|
|
|
|
|
|
|
@http_env_keys, |
37
|
|
|
|
|
|
|
); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub new { |
40
|
611
|
|
|
611
|
1
|
81464
|
my ($self, @args) = @_; |
41
|
611
|
50
|
|
|
|
1740
|
if (@args == 1) { |
42
|
0
|
|
|
|
|
0
|
@args = ('env' => $args[0]); |
43
|
0
|
|
|
|
|
0
|
Dancer::Deprecation->deprecated( |
44
|
|
|
|
|
|
|
fatal => 1, |
45
|
|
|
|
|
|
|
feature => 'Calling Dancer::Request->new($env)', |
46
|
|
|
|
|
|
|
version => 1.3059, |
47
|
|
|
|
|
|
|
reason => 'Please use Dancer::Request->new( env => $env ) instead', |
48
|
|
|
|
|
|
|
); |
49
|
|
|
|
|
|
|
} |
50
|
611
|
|
|
|
|
2882
|
$self->SUPER::new(@args); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# aliases |
54
|
1
|
|
|
1
|
1
|
5
|
sub agent { $_[0]->user_agent } |
55
|
19
|
|
|
19
|
1
|
59
|
sub remote_address { $_[0]->address } |
56
|
1
|
50
|
|
1
|
1
|
6
|
sub forwarded_for_address { $_[0]->env->{'X_FORWARDED_FOR'} || $_[0]->env->{'HTTP_X_FORWARDED_FOR'} } |
57
|
|
|
|
|
|
|
sub address { |
58
|
|
|
|
|
|
|
setting('behind_proxy') |
59
|
|
|
|
|
|
|
? $_[0]->forwarded_for_address() |
60
|
|
|
|
|
|
|
: $_[0]->env->{REMOTE_ADDR} |
61
|
19
|
50
|
|
19
|
1
|
51
|
} |
62
|
|
|
|
|
|
|
sub host { |
63
|
34
|
50
|
|
34
|
1
|
99
|
if (@_==2) { |
64
|
0
|
|
|
|
|
0
|
$_[0]->{host} = $_[1]; |
65
|
|
|
|
|
|
|
} else { |
66
|
34
|
|
|
|
|
58
|
my $host; |
67
|
34
|
100
|
33
|
|
|
114
|
$host = ($_[0]->env->{X_FORWARDED_HOST} || $_[0]->env->{HTTP_X_FORWARDED_HOST}) if setting('behind_proxy'); |
68
|
34
|
100
|
100
|
|
|
343
|
$host || $_[0]->{host} || $_[0]->env->{HTTP_HOST}; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
} |
71
|
0
|
|
|
0
|
1
|
0
|
sub remote_host { $_[0]->env->{REMOTE_HOST} } |
72
|
1
|
|
|
1
|
1
|
5
|
sub protocol { $_[0]->env->{SERVER_PROTOCOL} } |
73
|
1
|
|
|
1
|
1
|
5
|
sub port { $_[0]->env->{SERVER_PORT} } |
74
|
617
|
|
|
617
|
1
|
2425
|
sub request_uri { $_[0]->env->{REQUEST_URI} } |
75
|
1
|
|
|
1
|
1
|
9
|
sub user { $_[0]->env->{REMOTE_USER} } |
76
|
622
|
|
|
622
|
1
|
1744
|
sub script_name { $_[0]->env->{SCRIPT_NAME} } |
77
|
1
|
50
|
|
1
|
1
|
5
|
sub request_base { $_[0]->env->{REQUEST_BASE} || $_[0]->env->{HTTP_REQUEST_BASE} } |
78
|
|
|
|
|
|
|
sub scheme { |
79
|
33
|
|
|
33
|
1
|
54
|
my $scheme; |
80
|
33
|
100
|
|
|
|
122
|
if (setting('behind_proxy')) { |
81
|
|
|
|
|
|
|
# PSGI specs say that X_FORWARDED_PROTO will |
82
|
|
|
|
|
|
|
# be converted into HTTP_X_FORWARDED_PROTO |
83
|
|
|
|
|
|
|
# but Dancer::Test doesn't use PSGI (for now) |
84
|
|
|
|
|
|
|
$scheme = $_[0]->env->{'HTTP_X_FORWARDED_PROTO'} |
85
|
|
|
|
|
|
|
|| $_[0]->env->{'X_FORWARDED_PROTOCOL'} |
86
|
|
|
|
|
|
|
|| $_[0]->env->{'HTTP_X_FORWARDED_PROTOCOL'} |
87
|
|
|
|
|
|
|
|| $_[0]->env->{'HTTP_FORWARDED_PROTO'} |
88
|
5
|
|
100
|
|
|
13
|
|| $_[0]->env->{'X_FORWARDED_PROTO'} |
89
|
|
|
|
|
|
|
|| "" |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
return $scheme |
92
|
|
|
|
|
|
|
|| $_[0]->env->{'psgi.url_scheme'} |
93
|
33
|
|
50
|
|
|
731
|
|| $_[0]->env->{'PSGI.URL_SCHEME'} |
94
|
|
|
|
|
|
|
|| ""; |
95
|
|
|
|
|
|
|
} |
96
|
1
|
|
|
1
|
1
|
4
|
sub secure { $_[0]->scheme eq 'https' } |
97
|
3
|
|
|
3
|
1
|
13
|
sub uri { $_[0]->request_uri } |
98
|
|
|
|
|
|
|
|
99
|
18
|
|
|
18
|
1
|
83
|
sub is_head { $_[0]->{method} eq 'HEAD' } |
100
|
10
|
|
|
10
|
1
|
71
|
sub is_post { $_[0]->{method} eq 'POST' } |
101
|
2
|
|
|
2
|
1
|
14
|
sub is_get { $_[0]->{method} eq 'GET' } |
102
|
15
|
|
|
15
|
1
|
89
|
sub is_put { $_[0]->{method} eq 'PUT' } |
103
|
2
|
|
|
2
|
1
|
34
|
sub is_delete { $_[0]->{method} eq 'DELETE' } |
104
|
1
|
|
|
1
|
1
|
25
|
sub is_patch { $_[0]->{method} eq 'PATCH' } |
105
|
7
|
|
|
7
|
1
|
30
|
sub header { $_[0]->{headers}->header($_[1]) } |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# We used to store the whole raw unparsed body; this was a big problem for large |
108
|
|
|
|
|
|
|
# file uploads (Issue 1129). |
109
|
|
|
|
|
|
|
# The original fix was to stop doing so, and replace the accessor with one that |
110
|
|
|
|
|
|
|
# would read it out of the temp file returned by HTTP::Body->body - but that |
111
|
|
|
|
|
|
|
# doesn't work for e.g. parsed form submissions, only certain types. |
112
|
|
|
|
|
|
|
# So, back to the older way - we may have a request body squirreled away |
113
|
|
|
|
|
|
|
# in memory if the config included the raw_request_body_in_ram boolean |
114
|
17
|
|
|
17
|
1
|
102
|
sub body { $_[0]->{body} } |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# public interface compat with CGI.pm objects |
117
|
1
|
|
|
1
|
1
|
5
|
sub request_method { method(@_) } |
118
|
2
|
|
|
2
|
1
|
7
|
sub Vars { params(@_) } |
119
|
615
|
100
|
|
615
|
1
|
1942
|
sub input_handle { $_[0]->env->{'psgi.input'} || $_[0]->env->{'PSGI.INPUT'} } |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub init { |
122
|
611
|
|
|
611
|
1
|
1343
|
my ($self) = @_; |
123
|
|
|
|
|
|
|
|
124
|
611
|
|
50
|
|
|
2105
|
$self->{env} ||= {}; |
125
|
611
|
|
|
|
|
2109
|
$self->{path} = undef; |
126
|
611
|
|
|
|
|
1147
|
$self->{method} = undef; |
127
|
611
|
|
|
|
|
1549
|
$self->{params} = {}; |
128
|
611
|
|
100
|
|
|
3084
|
$self->{is_forward} ||= 0; |
129
|
611
|
|
100
|
|
|
2166
|
$self->{content_length} = $self->env->{CONTENT_LENGTH} || 0; |
130
|
611
|
|
100
|
|
|
1545
|
$self->{content_type} = $self->env->{CONTENT_TYPE} || ''; |
131
|
611
|
|
|
|
|
2061
|
$self->{id} = ++$count; |
132
|
611
|
|
|
|
|
1439
|
$self->{_chunk_size} = 4096; |
133
|
611
|
|
|
|
|
1062
|
$self->{_read_position} = 0; |
134
|
611
|
|
|
|
|
1272
|
$self->{_body_params} = undef; |
135
|
611
|
|
|
|
|
1041
|
$self->{_query_params} = undef; |
136
|
611
|
|
|
|
|
1475
|
$self->{_route_params} = {}; |
137
|
|
|
|
|
|
|
|
138
|
611
|
|
|
|
|
1897
|
$self->_build_headers(); |
139
|
611
|
|
|
|
|
1867
|
$self->_build_request_env(); |
140
|
611
|
50
|
|
|
|
1780
|
$self->_build_path() unless $self->path; |
141
|
611
|
50
|
|
|
|
1926
|
$self->_build_path_info() unless $self->path_info; |
142
|
611
|
50
|
|
|
|
1806
|
$self->_build_method() unless $self->method; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
$self->{_http_body} |
145
|
611
|
|
|
|
|
1892
|
= HTTP::Body->new($self->content_type, $self->content_length); |
146
|
611
|
|
|
|
|
45846
|
$self->{_http_body}->cleanup(1); |
147
|
611
|
|
|
|
|
4308
|
$self->{body} = ''; # default, because we might not store it now. |
148
|
611
|
|
|
|
|
2510
|
$self->_build_params(); |
149
|
611
|
50
|
|
|
|
2186
|
$self->_build_uploads unless $self->uploads; |
150
|
611
|
|
|
|
|
1847
|
$self->{ajax} = $self->is_ajax; |
151
|
|
|
|
|
|
|
|
152
|
611
|
|
|
|
|
1501
|
return $self; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub to_string { |
156
|
1
|
|
|
1
|
1
|
3
|
my ($self) = @_; |
157
|
1
|
|
|
|
|
5
|
return "[#" . $self->id . "] " . $self->method . " " . $self->path; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# helper for building a request object by hand |
161
|
|
|
|
|
|
|
# with the given method, path, params, body and headers. |
162
|
|
|
|
|
|
|
sub new_for_request { |
163
|
571
|
|
|
571
|
1
|
3601
|
my ($class, $method, $uri, $params, $body, $headers, $extra_env) = @_; |
164
|
571
|
|
100
|
|
|
2523
|
$params ||= {}; |
165
|
571
|
|
100
|
|
|
1863
|
$extra_env ||= {}; |
166
|
571
|
|
|
|
|
1339
|
$method = uc($method); |
167
|
|
|
|
|
|
|
|
168
|
571
|
|
|
|
|
3771
|
my ( $path, $query_string ) = ( $uri =~ /([^?]*)(?:\?(.*))?/s ); #from HTTP::Server::Simple |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
my $env = { |
171
|
|
|
|
|
|
|
%ENV, |
172
|
571
|
|
|
|
|
14619
|
%{$extra_env}, |
173
|
|
|
|
|
|
|
PATH_INFO => $path, |
174
|
571
|
|
100
|
|
|
5156
|
QUERY_STRING => $query_string || $ENV{QUERY_STRING} || '', |
175
|
|
|
|
|
|
|
REQUEST_METHOD => $method |
176
|
|
|
|
|
|
|
}; |
177
|
571
|
100
|
|
|
|
3533
|
$env->{CONTENT_LENGTH} = defined($body) ? length($body) : 0 if !exists $env->{CONTENT_LENGTH}; |
|
|
100
|
|
|
|
|
|
178
|
571
|
|
|
|
|
1938
|
my $req = $class->new(env => $env); |
179
|
571
|
|
|
|
|
927
|
$req->{params} = {%{$req->{params}}, %{$params}}; |
|
571
|
|
|
|
|
1251
|
|
|
571
|
|
|
|
|
1298
|
|
180
|
571
|
|
|
|
|
1629
|
$req->_build_params(); |
181
|
571
|
|
|
|
|
1222
|
$req->{_query_params} = $req->{params}; |
182
|
571
|
|
|
|
|
2013
|
my $store_raw_body = setting('raw_request_body_in_ram'); |
183
|
571
|
50
|
|
|
|
1422
|
$store_raw_body = defined $store_raw_body ? $store_raw_body : 1; |
184
|
571
|
50
|
|
|
|
1266
|
if ($store_raw_body) { |
185
|
571
|
|
|
|
|
1056
|
$req->{body} = $body; |
186
|
|
|
|
|
|
|
} |
187
|
571
|
|
66
|
|
|
1735
|
$req->{headers} = $headers || HTTP::Headers->new; |
188
|
|
|
|
|
|
|
|
189
|
571
|
|
|
|
|
2693
|
return $req; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
#Create a new request which is a clone of the current one, apart |
193
|
|
|
|
|
|
|
#from the path location, which points instead to the new location |
194
|
|
|
|
|
|
|
sub forward { |
195
|
16
|
|
|
16
|
1
|
40
|
my ($class, $request, $to_data) = @_; |
196
|
|
|
|
|
|
|
|
197
|
16
|
|
|
|
|
43
|
my $env = $request->env; |
198
|
16
|
|
|
|
|
37
|
$env->{PATH_INFO} = $to_data->{to_url}; |
199
|
|
|
|
|
|
|
|
200
|
16
|
|
|
|
|
45
|
my $new_request = $class->new(env => $env, is_forward => 1); |
201
|
|
|
|
|
|
|
my $new_params = _merge_params(scalar($request->params), |
202
|
16
|
|
100
|
|
|
51
|
$to_data->{params} || {}); |
203
|
|
|
|
|
|
|
|
204
|
16
|
100
|
|
|
|
49
|
if (exists($to_data->{options}{method})) { |
205
|
2
|
50
|
|
|
|
23
|
die unless _valid_method($to_data->{options}{method}); |
206
|
2
|
|
|
|
|
5
|
$new_request->{method} = uc $to_data->{options}{method}; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
16
|
|
|
|
|
27
|
$new_request->{params} = $new_params; |
210
|
16
|
|
|
|
|
34
|
$new_request->{_body_params} = $request->{_body_params}; |
211
|
16
|
|
|
|
|
31
|
$new_request->{_query_params} = $request->{_query_params}; |
212
|
16
|
|
|
|
|
34
|
$new_request->{_route_params} = $request->{_route_params}; |
213
|
16
|
|
|
|
|
28
|
$new_request->{_params_are_decoded} = 1; |
214
|
16
|
|
|
|
|
41
|
$new_request->{headers} = $request->headers; |
215
|
|
|
|
|
|
|
|
216
|
16
|
100
|
66
|
|
|
74
|
if( my $session = Dancer::Session->engine |
217
|
|
|
|
|
|
|
&& Dancer::Session->get_current_session ) { |
218
|
15
|
|
|
|
|
33
|
my $name = $session->session_name; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# make sure that COOKIE is populated |
221
|
15
|
|
33
|
|
|
77
|
$new_request->{env}{COOKIE} ||= $new_request->{env}{HTTP_COOKIE}; |
222
|
|
|
|
|
|
|
|
223
|
182
|
|
|
182
|
|
1729
|
no warnings; # COOKIE can be undef |
|
182
|
|
|
|
|
798
|
|
|
182
|
|
|
|
|
535215
|
|
224
|
15
|
50
|
|
|
|
138
|
unless ( $new_request->{env}{COOKIE} =~ /$name\s*=/ ) { |
225
|
|
|
|
|
|
|
$new_request->{env}{COOKIE} = join ';', |
226
|
30
|
|
|
|
|
85
|
grep { $_ } |
227
|
|
|
|
|
|
|
$new_request->{env}{COOKIE}, |
228
|
15
|
|
|
|
|
54
|
join '=', $name, Dancer::Session->get_current_session->id; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
16
|
|
|
|
|
58
|
$new_request->{uploads} = $request->uploads; |
233
|
|
|
|
|
|
|
|
234
|
16
|
|
|
|
|
59
|
return $new_request; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub _valid_method { |
238
|
2
|
|
|
2
|
|
8
|
my $method = shift; |
239
|
2
|
|
|
|
|
21
|
return $method =~ /^(?:head|post|get|put|delete)$/i; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub _merge_params { |
243
|
16
|
|
|
16
|
|
34
|
my ($params, $to_add) = @_; |
244
|
|
|
|
|
|
|
|
245
|
16
|
50
|
|
|
|
40
|
die unless ref $to_add eq "HASH"; |
246
|
16
|
|
|
|
|
44
|
for my $key (keys %$to_add) { |
247
|
4
|
|
|
|
|
11
|
$params->{$key} = $to_add->{$key}; |
248
|
|
|
|
|
|
|
} |
249
|
16
|
|
|
|
|
32
|
return $params; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub base { |
253
|
29
|
|
|
29
|
1
|
1632
|
my $self = shift; |
254
|
29
|
|
|
|
|
82
|
my $uri = $self->_common_uri; |
255
|
|
|
|
|
|
|
|
256
|
29
|
|
|
|
|
103
|
return $uri->canonical; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub _common_uri { |
260
|
32
|
|
|
32
|
|
51
|
my $self = shift; |
261
|
|
|
|
|
|
|
|
262
|
32
|
|
100
|
|
|
94
|
my $path = $self->env->{SCRIPT_NAME} || ''; |
263
|
32
|
|
|
|
|
79
|
my $port = $self->env->{SERVER_PORT}; |
264
|
32
|
|
|
|
|
89
|
my $server = $self->env->{SERVER_NAME}; |
265
|
32
|
|
|
|
|
100
|
my $host = $self->host; |
266
|
32
|
|
|
|
|
131
|
my $scheme = $self->scheme; |
267
|
|
|
|
|
|
|
|
268
|
32
|
|
|
|
|
157
|
my $uri = URI->new; |
269
|
32
|
|
|
|
|
41840
|
$uri->scheme($scheme); |
270
|
32
|
|
66
|
|
|
36026
|
$uri->authority($host || "$server:$port"); |
271
|
32
|
100
|
|
|
|
1627
|
if (setting('behind_proxy')) { |
272
|
5
|
|
100
|
|
|
16
|
my $request_base = $self->env->{REQUEST_BASE} || $self->env->{HTTP_REQUEST_BASE} || ''; |
273
|
5
|
|
100
|
|
|
40
|
$uri->path($request_base . $path || '/'); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
else { |
276
|
27
|
|
100
|
|
|
334
|
$uri->path($path || '/'); |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
32
|
|
|
|
|
1257
|
return $uri; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub uri_base { |
283
|
3
|
|
|
3
|
1
|
29
|
my $self = shift; |
284
|
3
|
|
|
|
|
10
|
my $uri = $self->_common_uri; |
285
|
3
|
|
|
|
|
14
|
my $canon = $uri->canonical; |
286
|
|
|
|
|
|
|
|
287
|
3
|
100
|
|
|
|
428
|
if ( $uri->path eq '/' ) { |
288
|
2
|
|
|
|
|
30
|
$canon =~ s{/$}{}; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
3
|
|
|
|
|
53
|
return $canon; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub uri_for { |
295
|
26
|
|
|
26
|
1
|
6847
|
my ($self, $part, $params, $dont_escape) = @_; |
296
|
26
|
|
|
|
|
78
|
my $uri = $self->base; |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Make sure there's exactly one slash between the base and the new part |
299
|
26
|
|
|
|
|
2816
|
my $base = $uri->path; |
300
|
26
|
|
|
|
|
305
|
$base =~ s|/$||; |
301
|
26
|
|
|
|
|
79
|
$part =~ s|^/||; |
302
|
26
|
|
|
|
|
107
|
$uri->path("$base/$part"); |
303
|
|
|
|
|
|
|
|
304
|
26
|
100
|
|
|
|
946
|
$uri->query_form($params) if $params; |
305
|
|
|
|
|
|
|
|
306
|
26
|
100
|
|
|
|
1124
|
return $dont_escape ? uri_unescape($uri->canonical) : $uri->canonical; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub params { |
310
|
436
|
|
|
436
|
1
|
1672
|
my ($self, $source) = @_; |
311
|
|
|
|
|
|
|
|
312
|
436
|
|
|
|
|
1400
|
my @caller = caller; |
313
|
|
|
|
|
|
|
|
314
|
436
|
100
|
|
|
|
1450
|
if (not $self->{_params_are_decoded}) { |
315
|
289
|
|
|
|
|
915
|
$self->{params} = _decode($self->{params}); |
316
|
289
|
|
|
|
|
714
|
$self->{_body_params} = _decode($self->{_body_params}); |
317
|
289
|
|
|
|
|
665
|
$self->{_query_params} = _decode($self->{_query_params}); |
318
|
289
|
|
|
|
|
826
|
$self->{_route_params} = _decode($self->{_route_params}); |
319
|
289
|
|
|
|
|
1430
|
$self->{_params_are_decoded} = 1; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
436
|
100
|
100
|
|
|
1222
|
return %{$self->{params}} if wantarray && @_ == 1; |
|
15
|
|
|
|
|
128
|
|
323
|
421
|
100
|
|
|
|
2270
|
return $self->{params} if @_ == 1; |
324
|
|
|
|
|
|
|
|
325
|
19
|
100
|
|
|
|
108
|
if ($source eq 'query') { |
|
|
50
|
|
|
|
|
|
326
|
4
|
100
|
|
|
|
17
|
return %{$self->{_query_params}} if wantarray; |
|
2
|
|
|
|
|
16
|
|
327
|
2
|
|
|
|
|
9
|
return $self->{_query_params}; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
elsif ($source eq 'body') { |
330
|
15
|
50
|
|
|
|
64
|
return %{$self->{_body_params}} if wantarray; |
|
0
|
|
|
|
|
0
|
|
331
|
15
|
|
|
|
|
66
|
return $self->{_body_params}; |
332
|
|
|
|
|
|
|
} |
333
|
0
|
0
|
|
|
|
0
|
if ($source eq 'route') { |
334
|
0
|
0
|
|
|
|
0
|
return %{$self->{_route_params}} if wantarray; |
|
0
|
|
|
|
|
0
|
|
335
|
0
|
|
|
|
|
0
|
return $self->{_route_params}; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
else { |
338
|
0
|
|
|
|
|
0
|
raise core_request => "Unknown source params \"$source\"."; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
sub _decode { |
343
|
2538
|
|
|
2538
|
|
7662
|
my ($h) = @_; |
344
|
2538
|
100
|
|
|
|
4942
|
return if not defined $h; |
345
|
|
|
|
|
|
|
|
346
|
2526
|
100
|
100
|
|
|
6161
|
if (!ref($h) && !utf8::is_utf8($h)) { |
347
|
622
|
|
|
|
|
2564
|
return decode('UTF-8', $h); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
1904
|
100
|
|
|
|
4163
|
if (ref($h) eq 'HASH') { |
351
|
1793
|
|
|
|
|
5494
|
while (my ($k, $v) = each(%$h)) { |
352
|
631
|
|
|
|
|
8218
|
$h->{$k} = _decode($v); |
353
|
|
|
|
|
|
|
} |
354
|
1793
|
|
|
|
|
22388
|
return $h; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
111
|
100
|
|
|
|
255
|
if (ref($h) eq 'ARRAY') { |
358
|
83
|
|
|
|
|
146
|
return [ map { _decode($_) } @$h ]; |
|
140
|
|
|
|
|
2548
|
|
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
28
|
|
|
|
|
93
|
return $h; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub is_ajax { |
365
|
614
|
|
|
614
|
1
|
1038
|
my $self = shift; |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# when using Plack::Builder headers are not set |
368
|
|
|
|
|
|
|
# so we're checking if it's actually there with PSGI plain headers |
369
|
614
|
50
|
|
|
|
1495
|
if ( defined $self->{x_requested_with} ) { |
370
|
0
|
0
|
|
|
|
0
|
if ( $self->{x_requested_with} eq "XMLHttpRequest" ) { |
371
|
0
|
|
|
|
|
0
|
return 1; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
614
|
100
|
|
|
|
1515
|
return 0 unless defined $self->headers; |
376
|
4
|
100
|
|
|
|
23
|
return 0 unless defined $self->header('X-Requested-With'); |
377
|
1
|
50
|
|
|
|
41
|
return 0 if $self->header('X-Requested-With') ne 'XMLHttpRequest'; |
378
|
1
|
|
|
|
|
44
|
return 1; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# context-aware accessor for uploads |
382
|
|
|
|
|
|
|
sub upload { |
383
|
8
|
|
|
8
|
1
|
986
|
my ($self, $name) = @_; |
384
|
8
|
|
|
|
|
22
|
my $res = $self->{uploads}{$name}; |
385
|
|
|
|
|
|
|
|
386
|
8
|
100
|
|
|
|
30
|
return $res unless wantarray; |
387
|
3
|
100
|
|
|
|
9
|
return () unless defined $res; |
388
|
2
|
100
|
|
|
|
12
|
return (ref($res) eq 'ARRAY') ? @$res : $res; |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# Some Dancer's core components sometimes need to alter |
392
|
|
|
|
|
|
|
# the parsed request params, these protected accessors are provided |
393
|
|
|
|
|
|
|
# for this purpose |
394
|
|
|
|
|
|
|
sub _set_route_params { |
395
|
649
|
|
|
649
|
|
1271
|
my ($self, $params) = @_; |
396
|
649
|
|
|
|
|
1496
|
$self->{_route_params} = $params; |
397
|
649
|
|
|
|
|
1465
|
$self->_build_params(); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
sub _set_body_params { |
401
|
8
|
|
|
8
|
|
22
|
my ($self, $params) = @_; |
402
|
8
|
|
|
|
|
19
|
$self->{_body_params} = $params; |
403
|
8
|
|
|
|
|
22
|
$self->_build_params(); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub _set_query_params { |
407
|
0
|
|
|
0
|
|
0
|
my ($self, $params) = @_; |
408
|
0
|
|
|
|
|
0
|
$self->{_query_params} = $params; |
409
|
0
|
|
|
|
|
0
|
$self->_build_params(); |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
sub _build_request_env { |
413
|
611
|
|
|
611
|
|
1147
|
my ($self) = @_; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# Don't refactor that, it's called whenever a request object is needed, that |
416
|
|
|
|
|
|
|
# means at least once per request. If refactored in a loop, this will cost 4 |
417
|
|
|
|
|
|
|
# times more than the following static map. |
418
|
611
|
|
|
|
|
1590
|
my $env = $self->env; |
419
|
611
|
|
|
|
|
1331
|
$self->{user_agent} = $env->{HTTP_USER_AGENT}; |
420
|
611
|
|
|
|
|
2042
|
$self->{host} = $env->{HTTP_HOST}; |
421
|
611
|
|
|
|
|
1253
|
$self->{accept_language} = $env->{HTTP_ACCEPT_LANGUAGE}; |
422
|
611
|
|
|
|
|
1625
|
$self->{accept_charset} = $env->{HTTP_ACCEPT_CHARSET}; |
423
|
611
|
|
|
|
|
1120
|
$self->{accept_encoding} = $env->{HTTP_ACCEPT_ENCODING}; |
424
|
611
|
|
|
|
|
1312
|
$self->{keep_alive} = $env->{HTTP_KEEP_ALIVE}; |
425
|
611
|
|
|
|
|
1266
|
$self->{connection} = $env->{HTTP_CONNECTION}; |
426
|
611
|
|
|
|
|
1274
|
$self->{accept} = $env->{HTTP_ACCEPT}; |
427
|
611
|
|
|
|
|
1238
|
$self->{accept_type} = $env->{HTTP_ACCEPT_TYPE}; |
428
|
611
|
|
|
|
|
1105
|
$self->{referer} = $env->{HTTP_REFERER}; |
429
|
611
|
|
|
|
|
1369
|
$self->{x_requested_with} = $env->{HTTP_X_REQUESTED_WITH}; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
sub _build_headers { |
433
|
611
|
|
|
611
|
|
1140
|
my ($self) = @_; |
434
|
611
|
|
|
|
|
2613
|
$self->{headers} = Dancer::SharedData->headers; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
sub _build_params { |
438
|
2450
|
|
|
2450
|
|
4762
|
my ($self) = @_; |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# params may have been populated by before filters |
441
|
|
|
|
|
|
|
# _before_ we get there, so we have to save it first |
442
|
2450
|
|
|
|
|
4047
|
my $previous = $self->{params}; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# now parse environment params... |
445
|
2450
|
|
|
|
|
6450
|
$self->_parse_get_params(); |
446
|
2450
|
100
|
|
|
|
5874
|
if ($self->is_forward) { |
447
|
47
|
|
100
|
|
|
132
|
$self->{_body_params} ||= {}; |
448
|
|
|
|
|
|
|
} else { |
449
|
2403
|
|
|
|
|
5459
|
$self->_parse_post_params(); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# and merge everything |
453
|
|
|
|
|
|
|
$self->{params} = { |
454
|
2450
|
|
|
|
|
4324
|
%$previous, %{$self->{_query_params}}, |
455
|
2450
|
|
|
|
|
8225
|
%{$self->{_route_params}}, %{$self->{_body_params}}, |
|
2450
|
|
|
|
|
4072
|
|
|
2450
|
|
|
|
|
6893
|
|
456
|
|
|
|
|
|
|
}; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# Written from PSGI specs: |
461
|
|
|
|
|
|
|
# http://search.cpan.org/dist/PSGI/PSGI.pod |
462
|
|
|
|
|
|
|
sub _build_path { |
463
|
611
|
|
|
611
|
|
1233
|
my ($self) = @_; |
464
|
611
|
|
|
|
|
1291
|
my $path = ""; |
465
|
|
|
|
|
|
|
|
466
|
611
|
100
|
|
|
|
1705
|
$path .= $self->script_name if defined $self->script_name; |
467
|
611
|
100
|
|
|
|
1520
|
$path .= $self->env->{PATH_INFO} if defined $self->env->{PATH_INFO}; |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# fallback to REQUEST_URI if nothing found |
470
|
|
|
|
|
|
|
# we have to decode it, according to PSGI specs. |
471
|
611
|
100
|
|
|
|
1633
|
if (defined $self->request_uri) { |
472
|
526
|
|
33
|
|
|
1793
|
$path ||= $self->_url_decode($self->request_uri); |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
|
475
|
611
|
50
|
|
|
|
1499
|
raise core_request => "Cannot resolve path" if not $path; |
476
|
611
|
|
|
|
|
1717
|
$self->{path} = $path; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
sub _build_path_info { |
480
|
611
|
|
|
611
|
|
1589
|
my ($self) = @_; |
481
|
611
|
|
|
|
|
1808
|
my $info = $self->env->{PATH_INFO}; |
482
|
611
|
100
|
|
|
|
1808
|
if (defined $info) { |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# Empty path info will be interpreted as "root". |
485
|
604
|
|
50
|
|
|
1679
|
$info ||= '/'; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
else { |
488
|
7
|
|
|
|
|
19
|
$info = $self->path; |
489
|
|
|
|
|
|
|
} |
490
|
611
|
|
|
|
|
1496
|
$self->{path_info} = $info; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
sub _build_method { |
494
|
611
|
|
|
611
|
|
1250
|
my ($self) = @_; |
495
|
|
|
|
|
|
|
$self->{method} = $self->env->{REQUEST_METHOD} |
496
|
611
|
|
33
|
|
|
2060
|
|| $self->{request}->request_method(); |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
sub _url_decode { |
500
|
80
|
|
|
80
|
|
161
|
my ($self, $encoded) = @_; |
501
|
80
|
|
|
|
|
117
|
my $clean = $encoded; |
502
|
80
|
|
|
|
|
121
|
$clean =~ tr/\+/ /; |
503
|
80
|
|
|
|
|
154
|
$clean =~ s/%([a-fA-F0-9]{2})/pack "H2", $1/eg; |
|
4
|
|
|
|
|
21
|
|
504
|
80
|
|
|
|
|
141
|
return $clean; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
sub _parse_post_params { |
508
|
2403
|
|
|
2403
|
|
4506
|
my ($self) = @_; |
509
|
2403
|
100
|
|
|
|
6068
|
return $self->{_body_params} if defined $self->{_body_params}; |
510
|
|
|
|
|
|
|
|
511
|
595
|
|
|
|
|
1968
|
$self->_read_to_end(); |
512
|
595
|
|
|
|
|
2615
|
$self->{_body_params} = $self->{_http_body}->param; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
sub _parse_get_params { |
516
|
2450
|
|
|
2450
|
|
4256
|
my ($self) = @_; |
517
|
2450
|
100
|
|
|
|
7517
|
return $self->{_query_params} if defined $self->{_query_params}; |
518
|
611
|
|
|
|
|
1788
|
$self->{_query_params} = {}; |
519
|
|
|
|
|
|
|
|
520
|
611
|
|
100
|
|
|
2120
|
my $source = $self->env->{QUERY_STRING} || ''; |
521
|
611
|
|
|
|
|
3047
|
foreach my $token (split /[&;]/, $source) { |
522
|
40
|
|
|
|
|
114
|
my ($key, $val) = split(/=/, $token, 2); |
523
|
40
|
50
|
|
|
|
91
|
next unless defined $key; |
524
|
40
|
50
|
|
|
|
82
|
$val = (defined $val) ? $val : ''; |
525
|
40
|
|
|
|
|
77
|
$key = $self->_url_decode($key); |
526
|
40
|
|
|
|
|
75
|
$val = $self->_url_decode($val); |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
# looking for multi-value params |
529
|
40
|
100
|
|
|
|
106
|
if (exists $self->{_query_params}{$key}) { |
530
|
4
|
|
|
|
|
11
|
my $prev_val = $self->{_query_params}{$key}; |
531
|
4
|
50
|
33
|
|
|
16
|
if (ref($prev_val) && ref($prev_val) eq 'ARRAY') { |
532
|
0
|
|
|
|
|
0
|
push @{$self->{_query_params}{$key}}, $val; |
|
0
|
|
|
|
|
0
|
|
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
else { |
535
|
4
|
|
|
|
|
13
|
$self->{_query_params}{$key} = [$prev_val, $val]; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
# simple value param (first time we see it) |
540
|
|
|
|
|
|
|
else { |
541
|
36
|
|
|
|
|
92
|
$self->{_query_params}{$key} = $val; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
} |
544
|
611
|
|
|
|
|
1539
|
return $self->{_query_params}; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
sub _read_to_end { |
548
|
595
|
|
|
595
|
|
1393
|
my $self = shift; |
549
|
|
|
|
|
|
|
|
550
|
595
|
100
|
|
|
|
2114
|
return unless $self->_has_something_to_read; |
551
|
|
|
|
|
|
|
|
552
|
32
|
100
|
|
|
|
147
|
if ( $self->content_length > 0 ) { |
553
|
20
|
|
|
|
|
47
|
my $body = ''; |
554
|
|
|
|
|
|
|
|
555
|
20
|
|
|
|
|
81
|
my $store_raw_body = setting('raw_request_body_in_ram'); |
556
|
20
|
50
|
|
|
|
63
|
$store_raw_body = defined $store_raw_body ? $store_raw_body : 1; |
557
|
|
|
|
|
|
|
|
558
|
20
|
|
|
|
|
60
|
while ( my $buffer = $self->_read ) { |
559
|
20
|
|
|
|
|
122
|
$self->{_http_body}->add($buffer); |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
# Only keep a copy of the raw request body in RAM if the user has |
562
|
|
|
|
|
|
|
# asked us to |
563
|
|
|
|
|
|
|
|
564
|
20
|
50
|
|
|
|
17828
|
if ($store_raw_body) { |
565
|
20
|
|
|
|
|
91
|
$self->{body} .= $buffer; |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
|
571
|
32
|
|
|
|
|
61
|
return $self->{_http_body}; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub _has_something_to_read { |
575
|
595
|
|
|
595
|
|
1997
|
defined $_[0]->input_handle; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
# taken from Miyagawa's Plack::Request::BodyParser |
579
|
|
|
|
|
|
|
sub _read { |
580
|
40
|
|
|
40
|
|
95
|
my ($self,) = @_; |
581
|
40
|
|
|
|
|
114
|
my $remaining = $self->content_length - $self->{_read_position}; |
582
|
40
|
|
|
|
|
81
|
my $maxlength = $self->{_chunk_size}; |
583
|
|
|
|
|
|
|
|
584
|
40
|
100
|
|
|
|
140
|
return if ($remaining <= 0); |
585
|
|
|
|
|
|
|
|
586
|
20
|
50
|
|
|
|
51
|
my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining; |
587
|
20
|
|
|
|
|
33
|
my $buffer; |
588
|
|
|
|
|
|
|
my $rc; |
589
|
|
|
|
|
|
|
|
590
|
20
|
|
|
|
|
50
|
$rc = $self->input_handle->read($buffer, $readlen); |
591
|
|
|
|
|
|
|
|
592
|
20
|
50
|
|
|
|
203
|
if (defined $rc) { |
593
|
20
|
|
|
|
|
42
|
$self->{_read_position} += $rc; |
594
|
20
|
|
|
|
|
75
|
return $buffer; |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
else { |
597
|
0
|
|
|
|
|
0
|
raise core_request => "Unknown error reading input: $!"; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
# Taken gently from Plack::Request, thanks to Plack authors. |
602
|
|
|
|
|
|
|
sub _build_uploads { |
603
|
611
|
|
|
611
|
|
1328
|
my ($self) = @_; |
604
|
|
|
|
|
|
|
|
605
|
611
|
|
|
|
|
2078
|
my $uploads = _decode($self->{_http_body}->upload); |
606
|
611
|
|
|
|
|
1230
|
my %uploads; |
607
|
|
|
|
|
|
|
|
608
|
611
|
|
|
|
|
865
|
for my $name (keys %{$uploads}) { |
|
611
|
|
|
|
|
1572
|
|
609
|
9
|
|
|
|
|
18
|
my $files = $uploads->{$name}; |
610
|
9
|
100
|
|
|
|
37
|
$files = ref $files eq 'ARRAY' ? $files : [$files]; |
611
|
|
|
|
|
|
|
|
612
|
9
|
|
|
|
|
13
|
my @uploads; |
613
|
9
|
|
|
|
|
17
|
for my $upload (@{$files}) { |
|
9
|
|
|
|
|
18
|
|
614
|
|
|
|
|
|
|
push( |
615
|
|
|
|
|
|
|
@uploads, |
616
|
|
|
|
|
|
|
Dancer::Request::Upload->new( |
617
|
|
|
|
|
|
|
headers => $upload->{headers}, |
618
|
|
|
|
|
|
|
tempname => $upload->{tempname}, |
619
|
|
|
|
|
|
|
size => $upload->{size}, |
620
|
|
|
|
|
|
|
filename => $upload->{filename}, |
621
|
|
|
|
|
|
|
) |
622
|
11
|
|
|
|
|
63
|
); |
623
|
|
|
|
|
|
|
} |
624
|
9
|
100
|
|
|
|
30
|
$uploads{$name} = @uploads > 1 ? \@uploads : $uploads[0]; |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# support access to the filename as a normal param |
627
|
9
|
|
|
|
|
19
|
my @filenames = map { $_->{filename} } @uploads; |
|
11
|
|
|
|
|
33
|
|
628
|
9
|
100
|
|
|
|
34
|
$self->{_body_params}{$name} = |
629
|
|
|
|
|
|
|
@filenames > 1 ? \@filenames : $filenames[0]; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
|
632
|
611
|
|
|
|
|
1710
|
$self->{uploads} = \%uploads; |
633
|
611
|
|
|
|
|
1298
|
$self->_build_params(); |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
1; |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
__END__ |