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