File Coverage

blib/lib/CatalystX/ASP/Request.pm
Criterion Covered Total %
statement 64 65 98.4
branch 24 30 80.0
condition 6 18 33.3
subroutine 12 12 100.0
pod 8 9 88.8
total 114 134 85.0


line stmt bran cond sub pod time code
1             package CatalystX::ASP::Request;
2              
3 9     9   4187 use namespace::autoclean;
  9         22  
  9         76  
4 9     9   757 use Moose;
  9         19  
  9         58  
5 9     9   59452 use List::Util qw(all);
  9         25  
  9         12055  
6              
7             has 'asp' => (
8             is => 'ro',
9             isa => 'CatalystX::ASP',
10             required => 1,
11             weak_ref => 1,
12             );
13              
14             =head1 NAME
15              
16             CatalystX::ASP::Request - $Request Object
17              
18             =head1 SYNOPSIS
19              
20             use CatalystX::ASP::Request;
21              
22             my $req = CatalystX::ASP::Request->new(asp => $asp);
23             my $session_cookie = $req->Cookies('session');
24             my $host = $req->ServerVariables('HTTP_HOST');
25              
26             =head1 DESCRIPTION
27              
28             The request object manages the input from the client browser, like posts, query
29             strings, cookies, etc. Normal return results are values if an index is
30             specified, or a collection / perl hash ref if no index is specified. WARNING:
31             the latter property is not supported in ActiveState PerlScript, so if you use
32             the hashes returned by such a technique, it will not be portable.
33              
34             A normal use of this feature would be to iterate through the form variables in
35             the form hash...
36              
37             $form = $Request->Form();
38             for(keys %{$form}) {
39             $Response->Write("$_: $form->{$_}<br>\n");
40             }
41              
42             Note that if a form POST or query string contains duplicate values for a key,
43             those values will be returned through normal use of the C<$Request> object:
44              
45             @values = $Request->Form('key');
46              
47             but you can also access the internal storage, which is an array reference like
48             so:
49              
50             $array_ref = $Request->{Form}{'key'};
51             @values = @{$array_ref};
52              
53             Please read the PERLSCRIPT section for more information on how things like
54             C<< $Request->QueryString() >> & C<< $Request->Form() >> behave as collections.
55              
56             =cut
57              
58             # For some reason, for attributes that start with a capital letter, Moose seems
59             # to load the default value before the object is fully initialized. lazy => 1 is
60             # a workaround to build the defaults later
61             has 'Cookies' => (
62             is => 'ro',
63             isa => 'HashRef',
64             reader => '_get_Cookies',
65             lazy => 1,
66             default => sub {
67             my ( $self ) = @_;
68             my $c = $self->asp->c;
69             my %cookies;
70             for my $name ( keys %{ $c->request->cookies } ) {
71             my $value = $c->request->cookies->{$name}{value} || [];
72             if ( all {/.=./} @$value ) {
73             for ( @$value ) {
74             my ( $key, $val ) = split '=';
75             $cookies{$name}{$key} = $val;
76             }
77             } else {
78             $cookies{$name} = $value->[0];
79             }
80             }
81             return \%cookies;
82             },
83             traits => ['Hash'],
84             handles => {
85             _get_Cookie => 'get',
86             },
87             );
88              
89             has 'FileUpload' => (
90             is => 'ro',
91             isa => 'HashRef',
92             reader => '_get_FileUploads',
93             lazy => 1,
94             default => sub {
95             my ( $self ) = @_;
96             my %uploads;
97             while ( my ( $field, $value ) = each %{ $self->asp->c->request->uploads } ) {
98              
99             # Just assume the first upload field, because how Apache::ASP deals with
100             # multiple uploads per-field is beyond me.
101             my $upload = ref( $value ) eq 'ARRAY' ? $value->[0] : $value;
102             $uploads{$field} = {
103             ContentType => $upload->type,
104             FileHandle => $upload->fh,
105             BrowserFile => $upload->filename,
106             TempFile => $upload->tempname,
107             };
108             }
109             return \%uploads;
110             },
111             traits => ['Hash'],
112             handles => {
113             _get_FileUpload => 'get',
114             },
115             );
116              
117             has 'Form' => (
118             is => 'ro',
119             isa => 'HashRef',
120             reader => '_get_Form',
121             lazy => 1,
122             default => sub {
123             my ( $self ) = @_;
124              
125             # ASP includes uploads in its Form()
126             return {
127             %{ $self->asp->c->request->body_parameters },
128             %{ $self->asp->c->request->uploads },
129             };
130             },
131             traits => ['Hash'],
132             handles => {
133             _get_FormField => 'get',
134             },
135             );
136              
137             =head1 ATTRIBUTES
138              
139             =over
140              
141             =item $Request->{Method}
142              
143             API extension. Returns the client HTTP request method, as in GET or POST. Added
144             in version C<2.31>.
145              
146             =cut
147              
148             has 'Method' => (
149             is => 'ro',
150             isa => 'Str',
151             lazy => 1,
152             default => sub { shift->asp->c->request->method },
153             );
154              
155             has 'Params' => (
156             is => 'ro',
157             isa => 'HashRef',
158             reader => '_get_Params',
159             lazy => 1,
160             default => sub { shift->asp->c->request->parameters },
161             traits => ['Hash'],
162             handles => {
163             _get_Param => 'get',
164             },
165             );
166              
167             has 'QueryString' => (
168             is => 'ro',
169             isa => 'HashRef',
170             reader => '_get_QueryString',
171             lazy => 1,
172             default => sub { shift->asp->c->request->query_parameters },
173             traits => ['Hash'],
174             handles => {
175             _get_Query => 'get',
176             },
177             );
178              
179             has 'ServerVariables' => (
180             is => 'ro',
181             isa => 'HashRef',
182             reader => '_get_ServerVariables',
183             lazy => 1,
184             default => sub {
185             my ( $self ) = @_;
186              
187             # Populate %ENV freely because we assume some process upstream will
188             # localize ENV for the request.
189             my $env = $self->asp->c->request->env;
190             for ( keys %$env ) {
191             $ENV{$_} = $env->{$_} unless ref $env->{$_};
192             }
193              
194             # For backwards compatibility with Apache::ASP
195             $ENV{SCRIPT_NAME} = $ENV{PATH_INFO};
196              
197             return \%ENV;
198             },
199             traits => ['Hash'],
200             handles => {
201             _get_ServerVariable => 'get',
202             },
203             );
204              
205             =item $Request->{TotalBytes}
206              
207             The amount of data sent by the client in the body of the request, usually the
208             length of the form data. This is the same value as
209             C<< $Request->ServerVariables('CONTENT_LENGTH') >>
210              
211             =cut
212              
213             has 'TotalBytes' => (
214             is => 'ro',
215             isa => 'Int',
216             lazy => 1,
217             default => sub { shift->asp->c->request->content_length || 0 },
218             );
219              
220             sub BUILD {
221 15     15 0 42 my ( $self ) = @_;
222              
223             # Don't initiate below attributes unless past setup phase
224 15 100       422 return unless $self->asp->_setup_finished;
225              
226             # Due to problem mentioned above in the builder methods, we are calling
227             # these attributes to populate the values for the hash key to be available
228 14         72 $self->Cookies;
229 14         58 $self->FileUpload;
230 14         51 $self->Form;
231 14         379 $self->Method;
232 14         54 $self->Params;
233 14         53 $self->QueryString;
234 14         64 $self->ServerVariables;
235 14         353 $self->TotalBytes;
236             }
237              
238             =back
239              
240             =head1 METHODS
241              
242             =over
243              
244             =item $Request->BinaryRead([$length])
245              
246             Returns a string whose contents are the first C<$length> bytes of the form data,
247             or body, sent by the client request. If C<$length> is not given, will return all
248             of the form data. This data is the raw data sent by the client, without any
249             parsing done on it by CatalystX::ASP.
250              
251             Note that C<BinaryRead> will not return any data for file uploads. Please see
252             the C<< $Request->FileUpload() >> interface for access to this data.
253             C<< $Request->Form() >> data will also be available as normal.
254              
255             =cut
256              
257             sub BinaryRead {
258 1     1 1 5 my ( $self, $length ) = @_;
259 1         23 my $c = $self->asp->c;
260 1         3 my $body = $c->request->body;
261 1         481 my @types = qw(application/x-www-form-urlencoded text/xml multipart/form-data);
262 1 50       2 if ( grep { $c->request->content_type eq $_ } @types ) {
  3         18  
263 1         8 my $buffer = '';
264 1   33     2 $length ||= $c->request->content_length;
265 1         7 $body->read( $buffer, $length );
266 1         14 return $buffer;
267             } else {
268 0         0 return substr( $body, 0, $length );
269             }
270             }
271              
272             =item $Request->ClientCertificate()
273              
274             Not implemented.
275              
276             =cut
277              
278             # TODO: will not implement
279             sub ClientCertificate {
280 1     1 1 1010 my ( $self ) = @_;
281 1         30 $self->asp->c->log->warn( "\$Request->ClientCertificate has not been implemented!" );
282 1         1481 return;
283             }
284              
285             =item $Request->Cookies($name [,$key])
286              
287             Returns the value of the Cookie with name C<$name>. If a C<$key> is specified,
288             then a lookup will be done on the cookie as if it were a query string. So, a
289             cookie set by:
290              
291             Set-Cookie: test=data1=1&data2=2
292              
293             would have a value of C<2> returned by C<< $Request->Cookies('test','data2') >>.
294              
295             If no name is specified, a hash will be returned of cookie names as keys and
296             cookie values as values. If the cookie value is a query string, it will
297             automatically be parsed, and the value will be a hash reference to these values.
298              
299             When in doubt, try it out. Remember that unless you set the C<Expires> attribute
300             of a cookie with C<< $Response->Cookies('cookie', 'Expires', $xyz) >>, the
301             cookies that you set will only last until you close your browser, so you may
302             find your self opening & closing your browser a lot when debugging cookies.
303              
304             For more information on cookies in ASP, please read C<< $Response->Cookies() >>
305              
306             =cut
307              
308             sub Cookies {
309 19     19 1 51 my ( $self, $name, $key ) = @_;
310              
311 19 100       59 if ( $name ) {
312 5 100       17 if ( $key ) {
313 3         97 my $cookie = $self->_get_Cookie( $name );
314 3 100       23 return ref $cookie eq 'HASH' ? $cookie->{$key} : $cookie;
315             } else {
316 2         77 return $self->_get_Cookie( $name );
317             }
318             } else {
319 14         386 return $self->_get_Cookies;
320             }
321             }
322              
323             =item $Request->FileUpload($form_field, $key)
324              
325             API extension. The C<FileUpload> interface to file upload data is stabilized.
326             The internal representation of the file uploads is a hash of hashes, one hash
327             per file upload found in the C<< $Request->Form() >> collection. This collection
328             of collections may be queried through the normal interface like so:
329              
330             $Request->FileUpload('upload_file', 'ContentType');
331             $Request->FileUpload('upload_file', 'FileHandle');
332             $Request->FileUpload('upload_file', 'BrowserFile');
333             $Request->FileUpload('upload_file', 'Mime-Header');
334             $Request->FileUpload('upload_file', 'TempFile');
335              
336             * note that TempFile must be use with the UploadTempFile configuration setting.
337              
338             The above represents the old slow collection interface, but like all collections
339             in CatalystX::ASP, you can reference the internal hash representation more
340             easily.
341              
342             my $fileup = $Request->{FileUpload}{upload_file};
343             $fileup->{ContentType};
344             $fileup->{BrowserFile};
345             $fileup->{FileHandle};
346             $fileup->{Mime-Header};
347             $fileup->{TempFile};
348              
349             =cut
350              
351             sub FileUpload {
352 16     16 1 53 my ( $self, $form_field, $key ) = @_;
353              
354 16 100       53 if ( $form_field ) {
355 2         73 my $upload = $self->_get_FileUpload( $form_field )->{$key};
356 2 50 33     10 return wantarray && ref $upload eq 'ARRAY' ? @$upload : $upload;
357             } else {
358 14         418 return $self->_get_FileUploads;
359             }
360             }
361              
362             =item $Request->Form($name)
363              
364             Returns the value of the input of name C<$name> used in a form with POST method.
365             If C<$name> is not specified, returns a ref to a hash of all the form data. One
366             can use this hash to create a nice alias to the form data like:
367              
368             # in global.asa
369             use vars qw( $Form );
370             sub Script_OnStart {
371             $Form = $Request->Form;
372             }
373             # then in ASP scripts
374             <%= $Form->{var} %>
375              
376             File upload data will be loaded into C<< $Request->Form('file_field') >>, where
377             the value is the actual file name of the file uploaded, and the contents of the
378             file can be found by reading from the file name as a file handle as in:
379              
380             while(read($Request->Form('file_field_name'), $data, 1024)) {};
381              
382             For more information, please see the CGI / File Upload section, as file uploads
383             are implemented via the CGI.pm module.
384              
385             =cut
386              
387             sub Form {
388 16     16 1 47 my ( $self, $name ) = @_;
389              
390 16 100       49 if ( $name ) {
391 1         36 my $value = $self->_get_FormField( $name );
392 1 50 33     6 return wantarray && ref $value eq 'ARRAY' ? @$value : $value;
393             } else {
394 15         428 return $self->_get_Form;
395             }
396             }
397              
398             =item $Request->Params($name)
399              
400             API extension. If C<RequestParams> CONFIG is set, the C<< $Request->Params >>
401             object is created with combined contents of C<< $Request->QueryString >> and
402             C<< $Request->Form >>. This is for developer convenience simlar to CGI.pm's
403             C<param()> method. Just like for C<< $Response->Form >>, one could create a
404             nice alias like:
405              
406             # in global.asa
407             use vars qw( $Params );
408             sub Script_OnStart {
409             $Params = $Request->Params;
410             }
411              
412             =cut
413              
414             sub Params {
415 16     16 1 570 my ( $self, $name ) = @_;
416              
417 16 100       51 if ( $name ) {
418 2         70 my $param = $self->_get_Param( $name );
419 2 50 33     10 return wantarray && ref $param eq 'ARRAY' ? @$param : $param;
420             } else {
421 14         406 return $self->_get_Params;
422             }
423             }
424              
425             =item $Request->QueryString($name)
426              
427             Returns the value of the input of name C<$name> used in a form with GET method,
428             or passed by appending a query string to the end of a url as in
429             http://localhost/?data=value. If C<$name> is not specified, returns a ref to a
430             hash of all the query string data.
431              
432             =cut
433              
434             sub QueryString {
435 15     15 1 41 my ( $self, $name ) = @_;
436              
437 15 100       43 if ( $name ) {
438 1         37 my $qparam = $self->_get_Query( $name );
439 1 50 33     6 return wantarray && ref $qparam eq 'ARRAY' ? @$qparam : $qparam;
440             } else {
441 14         409 return $self->_get_QueryString;
442             }
443             }
444              
445             =item $Request->ServerVariables($name)
446              
447             Returns the value of the server variable / environment variable with name
448             C<$name>. If C<$name> is not specified, returns a ref to a hash of all the
449             server / environment variables data. The following would be a common use of
450             this method:
451              
452             $env = $Request->ServerVariables();
453             # %{$env} here would be equivalent to the cgi %ENV in perl.
454              
455             =cut
456              
457             sub ServerVariables {
458 15     15 1 48 my ( $self, $name ) = @_;
459              
460 15 100       66 if ( $name ) {
461 1         37 my $var = $self->_get_ServerVariable( $name );
462 1 50 33     9 return wantarray && ref $var eq 'ARRAY' ? @$var : $var;
463             } else {
464 14         458 return $self->_get_ServerVariables;
465             }
466             }
467              
468             __PACKAGE__->meta->make_immutable;
469              
470             =back
471              
472             =head1 SEE ALSO
473              
474             =over
475              
476             =item * L<CatalystX::ASP::Session>
477              
478             =item * L<CatalystX::ASP::Response>
479              
480             =item * L<CatalystX::ASP::Application>
481              
482             =item * L<CatalystX::ASP::Server>
483              
484             =back