Move prepare_parametrs to be the builder.
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Request.pm
1 package Catalyst::Request;
2
3 use IO::Socket qw[AF_INET inet_aton];
4 use Carp;
5 use utf8;
6 use URI::http;
7 use URI::https;
8 use URI::QueryParam;
9 use HTTP::Headers;
10
11 use Moose;
12
13 use namespace::clean -except => 'meta';
14
15 with 'MooseX::Emulate::Class::Accessor::Fast';
16
17 has env => (is => 'ro', writer => '_set_env');
18
19 has _read_position => ( is => 'rw', default => 0 );
20 has _read_length => ( is => 'ro',
21     default => sub {
22         my $self = shift;
23         $self->header('Content-Length') || 0;
24     },
25     lazy => 1,
26 );
27
28 has action => (is => 'rw');
29 has address => (is => 'rw');
30 has arguments => (is => 'rw', default => sub { [] });
31 has cookies => (is => 'rw', default => sub { {} });
32 has query_keywords => (is => 'rw');
33 has match => (is => 'rw');
34 has method => (is => 'rw');
35 has protocol => (is => 'rw');
36 has query_parameters  => (is => 'rw', default => sub { {} });
37 has secure => (is => 'rw', default => 0);
38 has captures => (is => 'rw', default => sub { [] });
39 has uri => (is => 'rw', predicate => 'has_uri');
40 has remote_user => (is => 'rw');
41 has headers => (
42   is      => 'rw',
43   isa     => 'HTTP::Headers',
44   handles => [qw(content_encoding content_length content_type header referer user_agent)],
45   default => sub { HTTP::Headers->new() },
46   required => 1,
47   lazy => 1,
48 );
49
50 has _context => (
51   is => 'rw',
52   weak_ref => 1,
53   clearer => '_clear_context',
54 );
55
56 # Amount of data to read from input on each pass
57 our $CHUNKSIZE = 64 * 1024;
58
59 sub read {
60     my ($self, $maxlength) = @_;
61     my $remaining = $self->_read_length - $self->_read_position;
62     $maxlength ||= $CHUNKSIZE;
63
64     # Are we done reading?
65     if ( $remaining <= 0 ) {
66         return;
67     }
68
69     my $readlen = ( $remaining > $maxlength ) ? $maxlength : $remaining;
70     my $rc = $self->read_chunk( my $buffer, $readlen );
71     if ( defined $rc ) {
72         if (0 == $rc) { # Nothing more to read even though Content-Length
73                         # said there should be.
74             return;
75         }
76         $self->_read_position( $self->_read_position + $rc );
77         return $buffer;
78     }
79     else {
80         Catalyst::Exception->throw(
81             message => "Unknown error reading input: $!" );
82     }
83 }
84
85 sub read_chunk {
86     my $self = shift;
87     return $self->env->{'psgi.input'}->read(@_);
88 }
89
90 has body_parameters => (
91   is => 'rw',
92   required => 1,
93   lazy => 1,
94   default => sub { {} },
95 );
96
97 has uploads => (
98   is => 'rw',
99   required => 1,
100   default => sub { {} },
101 );
102
103 has parameters => (
104     is => 'rw',
105     lazy => 1,
106     builder => 'prepare_parameters',
107 );
108
109 # TODO:
110 # - Can we lose the before modifiers which just call prepare_body ?
111 #   they are wasteful, slow us down and feel cluttery.
112
113 #  Can we make _body an attribute, have the rest of
114 #  these lazy build from there and kill all the direct hash access
115 #  in Catalyst.pm and Engine.pm?
116
117 sub prepare_parameters {
118     my ( $self ) = @_;
119
120     $self->prepare_body;
121     my $parameters = {};
122     my $body_parameters = $self->body_parameters;
123     my $query_parameters = $self->query_parameters;
124     # We copy, no references
125     foreach my $name (keys %$query_parameters) {
126         my $param = $query_parameters->{$name};
127         $parameters->{$name} = ref $param eq 'ARRAY' ? [ @$param ] : $param;
128     }
129
130     # Merge query and body parameters
131     foreach my $name (keys %$body_parameters) {
132         my $param = $body_parameters->{$name};
133         my @values = ref $param eq 'ARRAY' ? @$param : ($param);
134         if ( my $existing = $parameters->{$name} ) {
135           unshift(@values, (ref $existing eq 'ARRAY' ? @$existing : $existing));
136         }
137         $parameters->{$name} = @values > 1 ? \@values : $values[0];
138     }
139     $parameters;
140 }
141
142 before body_parameters => sub {
143     my ($self) = @_;
144     $self->prepare_body;
145     $self->prepare_body_parameters;
146 };
147
148 =head2 $self->prepare_body()
149
150 sets up the L<Catalyst::Request> object body using L<HTTP::Body>
151
152 =cut
153
154 has _uploadtmp => (
155     is => 'ro',
156     predicate => '_has_uploadtmp',
157 );
158
159 sub prepare_body {
160     my ( $self ) = @_;
161
162     if ( my $length = $self->_read_length ) {
163         unless ( $self->_body ) {
164             my $type = $self->header('Content-Type');
165             $self->_body(HTTP::Body->new( $type, $length ));
166             $self->_body->cleanup(1); # Make extra sure!
167             $self->_body->tmpdir( $self->_uploadtmp )
168               if $self->_has_uploadtmp;
169         }
170
171         # Check for definedness as you could read '0'
172         while ( defined ( my $buffer = $self->read() ) ) {
173             $self->prepare_body_chunk($buffer);
174         }
175
176         # paranoia against wrong Content-Length header
177         my $remaining = $length - $self->_read_position;
178         if ( $remaining > 0 ) {
179             Catalyst::Exception->throw(
180                 "Wrong Content-Length value: $length" );
181         }
182     }
183     else {
184         # Defined but will cause all body code to be skipped
185         $self->_body(0);
186     }
187 }
188
189 =head2 $self->prepare_body_chunk()
190
191 Add a chunk to the request body.
192
193 =cut
194
195 sub prepare_body_chunk {
196     my ( $self, $chunk ) = @_;
197
198     $self->_body->add($chunk);
199 }
200
201 =head2 $self->prepare_body_parameters()
202
203 Sets up parameters from body.
204
205 =cut
206
207 sub prepare_body_parameters {
208     my ( $self ) = @_;
209
210     return unless $self->_body;
211
212     $self->{body_parameters} = $self->_body->param; # FIXME!! Recursion here.
213 }
214
215 around parameters => sub {
216     my ($orig, $self, $params) = @_;
217     if ($params) {
218         if ( !ref $params ) {
219             $self->_context->log->warn(
220                 "Attempt to retrieve '$params' with req->params(), " .
221                 "you probably meant to call req->param('$params')"
222             );
223             $params = undef;
224         }
225         return $self->$orig($params);
226     }
227     $self->$orig();
228 };
229
230 has base => (
231   is => 'rw',
232   required => 1,
233   lazy => 1,
234   default => sub {
235     my $self = shift;
236     return $self->path if $self->has_uri;
237   },
238 );
239
240 has _body => (
241   is => 'rw', clearer => '_clear_body', predicate => '_has_body',
242 );
243 # Eugh, ugly. Should just be able to rename accessor methods to 'body'
244 #             and provide a custom reader..
245 sub body {
246   my $self = shift;
247   $self->prepare_body();
248   croak 'body is a reader' if scalar @_;
249   return blessed $self->_body ? $self->_body->body : $self->_body;
250 }
251
252 has hostname => (
253   is        => 'rw',
254   required  => 1,
255   lazy      => 1,
256   default   => sub {
257     my ($self) = @_;
258     gethostbyaddr( inet_aton( $self->address ), AF_INET ) || $self->address
259   },
260 );
261
262 has _path => ( is => 'rw', predicate => '_has_path', clearer => '_clear_path' );
263
264 # XXX: Deprecated in docs ages ago (2006), deprecated with warning in 5.8000 due
265 # to confusion between Engines and Plugin::Authentication. Remove in 5.8100?
266 has user => (is => 'rw');
267
268 sub args            { shift->arguments(@_) }
269 sub body_params     { shift->body_parameters(@_) }
270 sub input           { shift->body(@_) }
271 sub params          { shift->parameters(@_) }
272 sub query_params    { shift->query_parameters(@_) }
273 sub path_info       { shift->path(@_) }
274 sub snippets        { shift->captures(@_) }
275
276 =for stopwords param params
277
278 =head1 NAME
279
280 Catalyst::Request - provides information about the current client request
281
282 =head1 SYNOPSIS
283
284     $req = $c->request;
285     $req->action;
286     $req->address;
287     $req->arguments;
288     $req->args;
289     $req->base;
290     $req->body;
291     $req->body_parameters;
292     $req->content_encoding;
293     $req->content_length;
294     $req->content_type;
295     $req->cookie;
296     $req->cookies;
297     $req->header;
298     $req->headers;
299     $req->hostname;
300     $req->input;
301     $req->query_keywords;
302     $req->match;
303     $req->method;
304     $req->param;
305     $req->parameters;
306     $req->params;
307     $req->path;
308     $req->protocol;
309     $req->query_parameters;
310     $req->read;
311     $req->referer;
312     $req->secure;
313     $req->captures; # previously knows as snippets
314     $req->upload;
315     $req->uploads;
316     $req->uri;
317     $req->user;
318     $req->user_agent;
319
320 See also L<Catalyst>, L<Catalyst::Request::Upload>.
321
322 =head1 DESCRIPTION
323
324 This is the Catalyst Request class, which provides an interface to data for the
325 current client request. The request object is prepared by L<Catalyst::Engine>,
326 thus hiding the details of the particular engine implementation.
327
328 =head1 METHODS
329
330 =head2 $req->action
331
332 [DEPRECATED] Returns the name of the requested action.
333
334
335 Use C<< $c->action >> instead (which returns a
336 L<Catalyst::Action|Catalyst::Action> object).
337
338 =head2 $req->address
339
340 Returns the IP address of the client.
341
342 =head2 $req->arguments
343
344 Returns a reference to an array containing the arguments.
345
346     print $c->request->arguments->[0];
347
348 For example, if your action was
349
350     package MyApp::Controller::Foo;
351
352     sub moose : Local {
353         ...
354     }
355
356 and the URI for the request was C<http://.../foo/moose/bah>, the string C<bah>
357 would be the first and only argument.
358
359 Arguments get automatically URI-unescaped for you.
360
361 =head2 $req->args
362
363 Shortcut for L</arguments>.
364
365 =head2 $req->base
366
367 Contains the URI base. This will always have a trailing slash. Note that the
368 URI scheme (e.g., http vs. https) must be determined through heuristics;
369 depending on your server configuration, it may be incorrect. See $req->secure
370 for more info.
371
372 If your application was queried with the URI
373 C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
374
375 =head2 $req->body
376
377 Returns the message body of the request, as returned by L<HTTP::Body>: a string,
378 unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
379 C<multipart/form-data>, in which case a L<File::Temp> object is returned.
380
381 =head2 $req->body_parameters
382
383 Returns a reference to a hash containing body (POST) parameters. Values can
384 be either a scalar or an arrayref containing scalars.
385
386     print $c->request->body_parameters->{field};
387     print $c->request->body_parameters->{field}->[0];
388
389 These are the parameters from the POST part of the request, if any.
390
391 =head2 $req->body_params
392
393 Shortcut for body_parameters.
394
395 =head2 $req->content_encoding
396
397 Shortcut for $req->headers->content_encoding.
398
399 =head2 $req->content_length
400
401 Shortcut for $req->headers->content_length.
402
403 =head2 $req->content_type
404
405 Shortcut for $req->headers->content_type.
406
407 =head2 $req->cookie
408
409 A convenient method to access $req->cookies.
410
411     $cookie  = $c->request->cookie('name');
412     @cookies = $c->request->cookie;
413
414 =cut
415
416 sub cookie {
417     my $self = shift;
418
419     if ( @_ == 0 ) {
420         return keys %{ $self->cookies };
421     }
422
423     if ( @_ == 1 ) {
424
425         my $name = shift;
426
427         unless ( exists $self->cookies->{$name} ) {
428             return undef;
429         }
430
431         return $self->cookies->{$name};
432     }
433 }
434
435 =head2 $req->cookies
436
437 Returns a reference to a hash containing the cookies.
438
439     print $c->request->cookies->{mycookie}->value;
440
441 The cookies in the hash are indexed by name, and the values are L<CGI::Simple::Cookie>
442 objects.
443
444 =head2 $req->header
445
446 Shortcut for $req->headers->header.
447
448 =head2 $req->headers
449
450 Returns an L<HTTP::Headers> object containing the headers for the current request.
451
452     print $c->request->headers->header('X-Catalyst');
453
454 =head2 $req->hostname
455
456 Returns the hostname of the client. Use C<< $req->uri->host >> to get the hostname of the server.
457
458 =head2 $req->input
459
460 Alias for $req->body.
461
462 =head2 $req->query_keywords
463
464 Contains the keywords portion of a query string, when no '=' signs are
465 present.
466
467     http://localhost/path?some+keywords
468
469     $c->request->query_keywords will contain 'some keywords'
470
471 =head2 $req->match
472
473 This contains the matching part of a Regex action. Otherwise
474 it returns the same as 'action', except for default actions,
475 which return an empty string.
476
477 =head2 $req->method
478
479 Contains the request method (C<GET>, C<POST>, C<HEAD>, etc).
480
481 =head2 $req->param
482
483 Returns GET and POST parameters with a CGI.pm-compatible param method. This
484 is an alternative method for accessing parameters in $c->req->parameters.
485
486     $value  = $c->request->param( 'foo' );
487     @values = $c->request->param( 'foo' );
488     @params = $c->request->param;
489
490 Like L<CGI>, and B<unlike> earlier versions of Catalyst, passing multiple
491 arguments to this method, like this:
492
493     $c->request->param( 'foo', 'bar', 'gorch', 'quxx' );
494
495 will set the parameter C<foo> to the multiple values C<bar>, C<gorch> and
496 C<quxx>. Previously this would have added C<bar> as another value to C<foo>
497 (creating it if it didn't exist before), and C<quxx> as another value for
498 C<gorch>.
499
500 B<NOTE> this is considered a legacy interface and care should be taken when
501 using it. C<< scalar $c->req->param( 'foo' ) >> will return only the first
502 C<foo> param even if multiple are present; C<< $c->req->param( 'foo' ) >> will
503 return a list of as many are present, which can have unexpected consequences
504 when writing code of the form:
505
506     $foo->bar(
507         a => 'b',
508         baz => $c->req->param( 'baz' ),
509     );
510
511 If multiple C<baz> parameters are provided this code might corrupt data or
512 cause a hash initialization error. For a more straightforward interface see
513 C<< $c->req->parameters >>.
514
515 =cut
516
517 sub param {
518     my $self = shift;
519
520     if ( @_ == 0 ) {
521         return keys %{ $self->parameters };
522     }
523
524     if ( @_ == 1 ) {
525
526         my $param = shift;
527
528         unless ( exists $self->parameters->{$param} ) {
529             return wantarray ? () : undef;
530         }
531
532         if ( ref $self->parameters->{$param} eq 'ARRAY' ) {
533             return (wantarray)
534               ? @{ $self->parameters->{$param} }
535               : $self->parameters->{$param}->[0];
536         }
537         else {
538             return (wantarray)
539               ? ( $self->parameters->{$param} )
540               : $self->parameters->{$param};
541         }
542     }
543     elsif ( @_ > 1 ) {
544         my $field = shift;
545         $self->parameters->{$field} = [@_];
546     }
547 }
548
549 =head2 $req->parameters
550
551 Returns a reference to a hash containing GET and POST parameters. Values can
552 be either a scalar or an arrayref containing scalars.
553
554     print $c->request->parameters->{field};
555     print $c->request->parameters->{field}->[0];
556
557 This is the combination of C<query_parameters> and C<body_parameters>.
558
559 =head2 $req->params
560
561 Shortcut for $req->parameters.
562
563 =head2 $req->path
564
565 Returns the path, i.e. the part of the URI after $req->base, for the current request.
566
567     http://localhost/path/foo
568
569     $c->request->path will contain 'path/foo'
570
571 =head2 $req->path_info
572
573 Alias for path, added for compatibility with L<CGI>.
574
575 =cut
576
577 sub path {
578     my ( $self, @params ) = @_;
579
580     if (@params) {
581         $self->uri->path(@params);
582         $self->_clear_path;
583     }
584     elsif ( $self->_has_path ) {
585         return $self->_path;
586     }
587     else {
588         my $path     = $self->uri->path;
589         my $location = $self->base->path;
590         $path =~ s/^(\Q$location\E)?//;
591         $path =~ s/^\///;
592         $self->_path($path);
593
594         return $path;
595     }
596 }
597
598 =head2 $req->protocol
599
600 Returns the protocol (HTTP/1.0 or HTTP/1.1) used for the current request.
601
602 =head2 $req->query_parameters
603
604 =head2 $req->query_params
605
606 Returns a reference to a hash containing query string (GET) parameters. Values can
607 be either a scalar or an arrayref containing scalars.
608
609     print $c->request->query_parameters->{field};
610     print $c->request->query_parameters->{field}->[0];
611
612 =head2 $req->read( [$maxlength] )
613
614 Reads a chunk of data from the request body. This method is intended to be
615 used in a while loop, reading $maxlength bytes on every call. $maxlength
616 defaults to the size of the request if not specified.
617
618 =head2 $req->read_chunk(\$buff, $max)
619
620 Reads a chunk..
621
622 You have to set MyApp->config(parse_on_demand => 1) to use this directly.
623
624 =head2 $req->referer
625
626 Shortcut for $req->headers->referer. Returns the referring page.
627
628 =head2 $req->secure
629
630 Returns true or false, indicating whether the connection is secure
631 (https). Note that the URI scheme (e.g., http vs. https) must be determined
632 through heuristics, and therefore the reliability of $req->secure will depend
633 on your server configuration. If you are serving secure pages on the standard
634 SSL port (443) and/or setting the HTTPS environment variable, $req->secure
635 should be valid.
636
637 =head2 $req->captures
638
639 Returns a reference to an array containing captured args from chained
640 actions or regex captures.
641
642     my @captures = @{ $c->request->captures };
643
644 =head2 $req->snippets
645
646 C<captures> used to be called snippets. This is still available for backwards
647 compatibility, but is considered deprecated.
648
649 =head2 $req->upload
650
651 A convenient method to access $req->uploads.
652
653     $upload  = $c->request->upload('field');
654     @uploads = $c->request->upload('field');
655     @fields  = $c->request->upload;
656
657     for my $upload ( $c->request->upload('field') ) {
658         print $upload->filename;
659     }
660
661 =cut
662
663 sub upload {
664     my $self = shift;
665
666     if ( @_ == 0 ) {
667         return keys %{ $self->uploads };
668     }
669
670     if ( @_ == 1 ) {
671
672         my $upload = shift;
673
674         unless ( exists $self->uploads->{$upload} ) {
675             return wantarray ? () : undef;
676         }
677
678         if ( ref $self->uploads->{$upload} eq 'ARRAY' ) {
679             return (wantarray)
680               ? @{ $self->uploads->{$upload} }
681               : $self->uploads->{$upload}->[0];
682         }
683         else {
684             return (wantarray)
685               ? ( $self->uploads->{$upload} )
686               : $self->uploads->{$upload};
687         }
688     }
689
690     if ( @_ > 1 ) {
691
692         while ( my ( $field, $upload ) = splice( @_, 0, 2 ) ) {
693
694             if ( exists $self->uploads->{$field} ) {
695                 for ( $self->uploads->{$field} ) {
696                     $_ = [$_] unless ref($_) eq "ARRAY";
697                     push( @$_, $upload );
698                 }
699             }
700             else {
701                 $self->uploads->{$field} = $upload;
702             }
703         }
704     }
705 }
706
707 =head2 $req->uploads
708
709 Returns a reference to a hash containing uploads. Values can be either a
710 L<Catalyst::Request::Upload> object, or an arrayref of
711 L<Catalyst::Request::Upload> objects.
712
713     my $upload = $c->request->uploads->{field};
714     my $upload = $c->request->uploads->{field}->[0];
715
716 =head2 $req->uri
717
718 Returns a L<URI> object for the current request. Stringifies to the URI text.
719
720 =head2 $req->mangle_params( { key => 'value' }, $appendmode);
721
722 Returns a hashref of parameters stemming from the current request's params,
723 plus the ones supplied.  Keys for which no current param exists will be
724 added, keys with undefined values will be removed and keys with existing
725 params will be replaced.  Note that you can supply a true value as the final
726 argument to change behavior with regards to existing parameters, appending
727 values rather than replacing them.
728
729 A quick example:
730
731   # URI query params foo=1
732   my $hashref = $req->mangle_params({ foo => 2 });
733   # Result is query params of foo=2
734
735 versus append mode:
736
737   # URI query params foo=1
738   my $hashref = $req->mangle_params({ foo => 2 }, 1);
739   # Result is query params of foo=1&foo=2
740
741 This is the code behind C<uri_with>.
742
743 =cut
744
745 sub mangle_params {
746     my ($self, $args, $append) = @_;
747
748     carp('No arguments passed to mangle_params()') unless $args;
749
750     foreach my $value ( values %$args ) {
751         next unless defined $value;
752         for ( ref $value eq 'ARRAY' ? @$value : $value ) {
753             $_ = "$_";
754             utf8::encode( $_ ) if utf8::is_utf8($_);
755         }
756     };
757
758     my %params = %{ $self->uri->query_form_hash };
759     foreach my $key (keys %{ $args }) {
760         my $val = $args->{$key};
761         if(defined($val)) {
762
763             if($append && exists($params{$key})) {
764
765                 # This little bit of heaven handles appending a new value onto
766                 # an existing one regardless if the existing value is an array
767                 # or not, and regardless if the new value is an array or not
768                 $params{$key} = [
769                     ref($params{$key}) eq 'ARRAY' ? @{ $params{$key} } : $params{$key},
770                     ref($val) eq 'ARRAY' ? @{ $val } : $val
771                 ];
772
773             } else {
774                 $params{$key} = $val;
775             }
776         } else {
777
778             # If the param wasn't defined then we delete it.
779             delete($params{$key});
780         }
781     }
782
783
784     return \%params;
785 }
786
787 =head2 $req->uri_with( { key => 'value' } );
788
789 Returns a rewritten URI object for the current request. Key/value pairs
790 passed in will override existing parameters. You can remove an existing
791 parameter by passing in an undef value. Unmodified pairs will be
792 preserved.
793
794 You may also pass an optional second parameter that puts C<uri_with> into
795 append mode:
796
797   $req->uri_with( { key => 'value' }, { mode => 'append' } );
798
799 See C<mangle_params> for an explanation of this behavior.
800
801 =cut
802
803 sub uri_with {
804     my( $self, $args, $behavior) = @_;
805
806     carp( 'No arguments passed to uri_with()' ) unless $args;
807
808     my $append = 0;
809     if((ref($behavior) eq 'HASH') && defined($behavior->{mode}) && ($behavior->{mode} eq 'append')) {
810         $append = 1;
811     }
812
813     my $params = $self->mangle_params($args, $append);
814
815     my $uri = $self->uri->clone;
816     $uri->query_form($params);
817
818     return $uri;
819 }
820
821 =head2 $req->remote_user
822
823 Returns the value of the C<REMOTE_USER> environment variable.
824
825 =head2 $req->user_agent
826
827 Shortcut to $req->headers->user_agent. Returns the user agent (browser)
828 version string.
829
830 =head2 meta
831
832 Provided by Moose
833
834 =head1 AUTHORS
835
836 Catalyst Contributors, see Catalyst.pm
837
838 =head1 COPYRIGHT
839
840 This library is free software. You can redistribute it and/or modify
841 it under the same terms as Perl itself.
842
843 =cut
844
845 __PACKAGE__->meta->make_immutable;
846
847 1;