Use Ref::Util where appropriate
[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 use Stream::Buffered;
11 use Hash::MultiValue;
12 use Scalar::Util;
13 use HTTP::Body;
14 use Catalyst::Exception;
15 use Catalyst::Request::PartData;
16 use Moose;
17 use Ref::Util qw(is_plain_arrayref is_plain_hashref);
18
19 use namespace::clean -except => 'meta';
20
21 with 'MooseX::Emulate::Class::Accessor::Fast';
22
23 has env => (is => 'ro', writer => '_set_env', predicate => '_has_env');
24 # XXX Deprecated crap here - warn?
25 has action => (is => 'rw');
26 # XXX: Deprecated in docs ages ago (2006), deprecated with warning in 5.8000 due
27 # to confusion between Engines and Plugin::Authentication. Remove in 5.8100?
28 has user => (is => 'rw');
29 sub snippets        { shift->captures(@_) }
30
31 has _read_position => (
32     # FIXME: work around Moose bug RT#75367
33     # init_arg => undef,
34     is => 'ro',
35     writer => '_set_read_position',
36     default => 0,
37 );
38 has _read_length => (
39     # FIXME: work around Moose bug RT#75367
40     # init_arg => undef,
41     is => 'ro',
42     default => sub {
43         my $self = shift;
44         $self->header('Content-Length') || 0;
45     },
46     lazy => 1,
47 );
48
49 has address => (is => 'rw');
50 has arguments => (is => 'rw', default => sub { [] });
51 has cookies => (is => 'ro', builder => 'prepare_cookies', lazy => 1);
52
53 sub prepare_cookies {
54     my ( $self ) = @_;
55
56     if ( my $header = $self->header('Cookie') ) {
57         return { CGI::Simple::Cookie->parse($header) };
58     }
59     {};
60 }
61
62 has query_keywords => (is => 'rw');
63 has match => (is => 'rw');
64 has method => (is => 'rw');
65 has protocol => (is => 'rw');
66 has query_parameters  => (is => 'rw', lazy=>1, default => sub { shift->_use_hash_multivalue ? Hash::MultiValue->new : +{} });
67 has secure => (is => 'rw', default => 0);
68 has captures => (is => 'rw', default => sub { [] });
69 has uri => (is => 'rw', predicate => 'has_uri');
70 has remote_user => (is => 'rw');
71 has headers => (
72   is      => 'rw',
73   isa     => 'HTTP::Headers',
74   handles => [qw(content_encoding content_length content_type header referer user_agent)],
75   builder => 'prepare_headers',
76   lazy => 1,
77 );
78
79 sub prepare_headers {
80     my ($self) = @_;
81
82     my $env = $self->env;
83     my $headers = HTTP::Headers->new();
84
85     for my $header (keys %{ $env }) {
86         next unless $header =~ /^(HTTP|CONTENT|COOKIE)/i;
87         (my $field = $header) =~ s/^HTTPS?_//;
88         $field =~ tr/_/-/;
89         $headers->header($field => $env->{$header});
90     }
91     return $headers;
92 }
93
94 has _log => (
95     is => 'ro',
96     weak_ref => 1,
97     required => 1,
98 );
99
100 has io_fh => (
101     is=>'ro',
102     predicate=>'_has_io_fh',
103     lazy=>1,
104     builder=>'_build_io_fh');
105
106 sub _build_io_fh {
107     my $self = shift;
108     return $self->env->{'psgix.io'}
109       || (
110         $self->env->{'net.async.http.server.req'} &&
111         $self->env->{'net.async.http.server.req'}->stream)   ## Until I can make ioasync cabal see the value of supportin psgix.io (jnap)
112       || die "Your Server does not support psgix.io";
113 };
114
115 has data_handlers => ( is=>'ro', isa=>'HashRef', default=>sub { +{} } );
116
117 has body_data => (
118     is=>'ro',
119     lazy=>1,
120     builder=>'_build_body_data');
121
122 sub _build_body_data {
123     my ($self) = @_;
124
125     # Not sure if these returns should not be exceptions...
126     my $content_type = $self->content_type || return;
127     return unless ($self->method eq 'POST' || $self->method eq 'PUT');
128
129     my ($match) = grep { $content_type =~/$_/i }
130       keys(%{$self->data_handlers});
131
132     if($match) {
133       my $fh = $self->body;
134       local $_ = $fh;
135       return $self->data_handlers->{$match}->($fh, $self);
136     } else { 
137       Catalyst::Exception->throw("$content_type is does not have an available data handler");
138     }
139 }
140
141 has _use_hash_multivalue => (
142     is=>'ro', 
143     required=>1, 
144     default=> sub {0});
145
146 # Amount of data to read from input on each pass
147 our $CHUNKSIZE = 64 * 1024;
148
149 sub read {
150     my ($self, $maxlength) = @_;
151     my $remaining = $self->_read_length - $self->_read_position;
152     $maxlength ||= $CHUNKSIZE;
153
154     # Are we done reading?
155     if ( $remaining <= 0 ) {
156         return;
157     }
158
159     my $readlen = ( $remaining > $maxlength ) ? $maxlength : $remaining;
160     my $rc = $self->read_chunk( my $buffer, $readlen );
161     if ( defined $rc ) {
162         if (0 == $rc) { # Nothing more to read even though Content-Length
163                         # said there should be.
164             return;
165         }
166         $self->_set_read_position( $self->_read_position + $rc );
167         return $buffer;
168     }
169     else {
170         Catalyst::Exception->throw(
171             message => "Unknown error reading input: $!" );
172     }
173 }
174
175 sub read_chunk {
176     my $self = shift;
177     return $self->env->{'psgi.input'}->read(@_);
178 }
179
180 has body_parameters => (
181   is => 'rw',
182   required => 1,
183   lazy => 1,
184   predicate => 'has_body_parameters',
185   builder => 'prepare_body_parameters',
186 );
187
188 has uploads => (
189   is => 'rw',
190   required => 1,
191   default => sub { {} },
192 );
193
194 has parameters => (
195     is => 'rw',
196     lazy => 1,
197     builder => '_build_parameters',
198     clearer => '_clear_parameters',
199 );
200
201 # TODO:
202 # - Can we lose the before modifiers which just call prepare_body ?
203 #   they are wasteful, slow us down and feel cluttery.
204
205 #  Can we make _body an attribute, have the rest of
206 #  these lazy build from there and kill all the direct hash access
207 #  in Catalyst.pm and Engine.pm?
208
209 sub prepare_parameters {
210     my ( $self ) = @_;
211     $self->_clear_parameters;
212     return $self->parameters;
213 }
214
215 sub _build_parameters {
216     my ( $self ) = @_;
217     my $parameters = {};
218     my $body_parameters = $self->body_parameters;
219     my $query_parameters = $self->query_parameters;
220
221     if($self->_use_hash_multivalue) {
222         return Hash::MultiValue->new($query_parameters->flatten, $body_parameters->flatten);
223     }
224
225     # We copy, no references
226     foreach my $name (keys %$query_parameters) {
227         my $param = $query_parameters->{$name};
228         $parameters->{$name} = is_plain_arrayref($param) ? [ @$param ] : $param;
229     }
230
231     # Merge query and body parameters
232     foreach my $name (keys %$body_parameters) {
233         my $param = $body_parameters->{$name};
234         my @values = is_plain_arrayref($param) ? @$param : ($param);
235         if ( my $existing = $parameters->{$name} ) {
236           unshift(@values, (is_plain_arrayref($existing) ? @$existing : $existing));
237         }
238         $parameters->{$name} = @values > 1 ? \@values : $values[0];
239     }
240     $parameters;
241 }
242
243 has _uploadtmp => (
244     is => 'ro',
245     predicate => '_has_uploadtmp',
246 );
247
248 sub prepare_body {
249     my ( $self ) = @_;
250
251     # If previously applied middleware created the HTTP::Body object, then we
252     # just use that one.  
253
254     if(my $plack_body = $self->_has_env ? $self->env->{'plack.request.http.body'} : undef) {
255         $self->_body($plack_body);
256         $self->_body->cleanup(1);
257         return;
258     }
259
260     # If there is nothing to read, set body to naught and return.  This
261     # will cause all body code to be skipped
262
263     return $self->_body(0) unless my $length = $self->_read_length;
264
265     # Unless the body has already been set, create it.  Not sure about this
266     # code, how else might it be set, but this was existing logic.
267
268     unless ($self->_body) {
269         my $type = $self->header('Content-Type');
270         $self->_body(HTTP::Body->new( $type, $length ));
271         $self->_body->cleanup(1);
272
273         # JNAP: I'm not sure this is doing what we expect, but it also doesn't
274         # seem to be hurting (seems ->_has_uploadtmp is true more than I would
275         # expect.
276
277         $self->_body->tmpdir( $self->_uploadtmp )
278           if $self->_has_uploadtmp;
279     }
280
281     # Ok if we get this far, we have to read psgi.input into the new body
282     # object.  Lets play nice with any plack app or other downstream, so
283     # we create a buffer unless one exists.
284      
285     my $stream_buffer;
286     if ($self->env->{'psgix.input.buffered'}) {
287         # Be paranoid about previous psgi middleware or apps that read the
288         # input but didn't return the buffer to the start.
289         $self->env->{'psgi.input'}->seek(0, 0);
290     } else {
291         $stream_buffer = Stream::Buffered->new($length);
292     }
293
294     # Check for definedness as you could read '0'
295     while ( defined ( my $chunk = $self->read() ) ) {
296         $self->prepare_body_chunk($chunk);
297         next unless $stream_buffer;
298
299         $stream_buffer->print($chunk)
300             || die sprintf "Failed to write %d bytes to psgi.input file: $!", length( $chunk );
301     }
302
303     # Ok, we read the body.  Lets play nice for any PSGI app down the pipe
304
305     if ($stream_buffer) {
306         $self->env->{'psgix.input.buffered'} = 1;
307         $self->env->{'psgi.input'} = $stream_buffer->rewind;
308     } else {
309         $self->env->{'psgi.input'}->seek(0, 0); # Reset the buffer for downstream middleware or apps
310     }
311
312     # paranoia against wrong Content-Length header
313     my $remaining = $length - $self->_read_position;
314     if ( $remaining > 0 ) {
315         Catalyst::Exception->throw("Wrong Content-Length value: $length" );
316     }
317 }
318
319 sub prepare_body_chunk {
320     my ( $self, $chunk ) = @_;
321
322     $self->_body->add($chunk);
323 }
324
325 sub prepare_body_parameters {
326     my ( $self, $c ) = @_;
327     return $self->body_parameters if $self->has_body_parameters;
328     $self->prepare_body if ! $self->_has_body;
329
330     unless($self->_body) {
331       my $return = $self->_use_hash_multivalue ? Hash::MultiValue->new : {};
332       $self->body_parameters($return);
333       return $return;
334     }
335
336     my $params;
337     my %part_data = %{$self->_body->part_data};
338     if(scalar %part_data && !$c->config->{skip_complex_post_part_handling}) {
339       foreach my $key (keys %part_data) {
340         my $proto_value = $part_data{$key};
341         my ($val, @extra) = is_plain_arrayref($proto_value) ? @$proto_value : ($proto_value);
342
343         $key = $c->_handle_param_unicode_decoding($key)
344           if ($c and $c->encoding and !$c->config->{skip_body_param_unicode_decoding});
345
346         if(@extra) {
347           $params->{$key} = [map { Catalyst::Request::PartData->build_from_part_data($c, $_) } ($val,@extra)];
348         } else {
349           $params->{$key} = Catalyst::Request::PartData->build_from_part_data($c, $val);
350         }
351       }
352     } else {
353       $params = $self->_body->param;
354
355       # If we have an encoding configured (like UTF-8) in general we expect a client
356       # to POST with the encoding we fufilled the request in. Otherwise don't do any
357       # encoding (good change wide chars could be in HTML entity style llike the old
358       # days -JNAP
359
360       # so, now that HTTP::Body prepared the body params, we gotta 'walk' the structure
361       # and do any needed decoding.
362
363       # This only does something if the encoding is set via the encoding param.  Remember
364       # this is assuming the client is not bad and responds with what you provided.  In
365       # general you can just use utf8 and get away with it.
366       #
367       # I need to see if $c is here since this also doubles as a builder for the object :(
368
369       if($c and $c->encoding and !$c->config->{skip_body_param_unicode_decoding}) {
370         $params = $c->_handle_unicode_decoding($params);
371       }
372     }
373
374     my $return = $self->_use_hash_multivalue ?
375         Hash::MultiValue->from_mixed($params) :
376         $params;
377
378     $self->body_parameters($return) unless $self->has_body_parameters;
379     return $return;
380 }
381
382 sub prepare_connection {
383     my ($self) = @_;
384
385     my $env = $self->env;
386
387     $self->address( $env->{REMOTE_ADDR} );
388     $self->hostname( $env->{REMOTE_HOST} )
389         if exists $env->{REMOTE_HOST};
390     $self->protocol( $env->{SERVER_PROTOCOL} );
391     $self->remote_user( $env->{REMOTE_USER} );
392     $self->method( $env->{REQUEST_METHOD} );
393     $self->secure( $env->{'psgi.url_scheme'} eq 'https' ? 1 : 0 );
394 }
395
396 # XXX - FIXME - method is here now, move this crap...
397 around parameters => sub {
398     my ($orig, $self, $params) = @_;
399     if ($params) {
400         if ( !ref $params ) {
401             $self->_log->warn(
402                 "Attempt to retrieve '$params' with req->params(), " .
403                 "you probably meant to call req->param('$params')"
404             );
405             $params = undef;
406         }
407         return $self->$orig($params);
408     }
409     $self->$orig();
410 };
411
412 has base => (
413   is => 'rw',
414   required => 1,
415   lazy => 1,
416   default => sub {
417     my $self = shift;
418     return $self->path if $self->has_uri;
419   },
420 );
421
422 has _body => (
423   is => 'rw', clearer => '_clear_body', predicate => '_has_body',
424 );
425 # Eugh, ugly. Should just be able to rename accessor methods to 'body'
426 #             and provide a custom reader..
427 sub body {
428   my $self = shift;
429   $self->prepare_body unless $self->_has_body;
430   croak 'body is a reader' if scalar @_;
431   return blessed $self->_body ? $self->_body->body : $self->_body;
432 }
433
434 has hostname => (
435   is        => 'rw',
436   required  => 1,
437   lazy      => 1,
438   default   => sub {
439     my ($self) = @_;
440     gethostbyaddr( inet_aton( $self->address ), AF_INET ) || $self->address
441   },
442 );
443
444 has _path => ( is => 'rw', predicate => '_has_path', clearer => '_clear_path' );
445
446 sub args            { shift->arguments(@_) }
447 sub body_params     { shift->body_parameters(@_) }
448 sub input           { shift->body(@_) }
449 sub params          { shift->parameters(@_) }
450 sub query_params    { shift->query_parameters(@_) }
451 sub path_info       { shift->path(@_) }
452
453 =for stopwords param params
454
455 =head1 NAME
456
457 Catalyst::Request - provides information about the current client request
458
459 =head1 SYNOPSIS
460
461     $req = $c->request;
462     $req->address eq "127.0.0.1";
463     $req->arguments;
464     $req->args;
465     $req->base;
466     $req->body;
467     $req->body_data;
468     $req->body_parameters;
469     $req->content_encoding;
470     $req->content_length;
471     $req->content_type;
472     $req->cookie;
473     $req->cookies;
474     $req->header;
475     $req->headers;
476     $req->hostname;
477     $req->input;
478     $req->query_keywords;
479     $req->match;
480     $req->method;
481     $req->param;
482     $req->parameters;
483     $req->params;
484     $req->path;
485     $req->protocol;
486     $req->query_parameters;
487     $req->read;
488     $req->referer;
489     $req->secure;
490     $req->captures;
491     $req->upload;
492     $req->uploads;
493     $req->uri;
494     $req->user;
495     $req->user_agent;
496     $req->env;
497
498 See also L<Catalyst>, L<Catalyst::Request::Upload>.
499
500 =head1 DESCRIPTION
501
502 This is the Catalyst Request class, which provides an interface to data for the
503 current client request. The request object is prepared by L<Catalyst::Engine>,
504 thus hiding the details of the particular engine implementation.
505
506 =head1 METHODS
507
508 =head2 $req->address
509
510 Returns the IP address of the client.
511
512 =head2 $req->arguments
513
514 Returns a reference to an array containing the arguments.
515
516     print $c->request->arguments->[0];
517
518 For example, if your action was
519
520     package MyApp::Controller::Foo;
521
522     sub moose : Local {
523         ...
524     }
525
526 and the URI for the request was C<http://.../foo/moose/bah>, the string C<bah>
527 would be the first and only argument.
528
529 Arguments get automatically URI-unescaped for you.
530
531 =head2 $req->args
532
533 Shortcut for L</arguments>.
534
535 =head2 $req->base
536
537 Contains the URI base. This will always have a trailing slash. Note that the
538 URI scheme (e.g., http vs. https) must be determined through heuristics;
539 depending on your server configuration, it may be incorrect. See $req->secure
540 for more info.
541
542 If your application was queried with the URI
543 C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
544
545 =head2 $req->body
546
547 Returns the message body of the request, as returned by L<HTTP::Body>: a string,
548 unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
549 C<multipart/form-data>, in which case a L<File::Temp> object is returned.
550
551 =head2 $req->body_data
552
553 Returns a Perl representation of POST/PUT body data that is not classic HTML
554 form data, such as JSON, XML, etc.  By default, Catalyst will parse incoming
555 data of the type 'application/json' and return access to that data via this
556 method.  You may define addition data_handlers via a global configuration
557 setting.  See L<Catalyst\DATA HANDLERS> for more information.
558
559 If the POST is malformed in some way (such as undefined or not content that
560 matches the content-type) we raise a L<Catalyst::Exception> with the error
561 text as the message.
562
563 If the POSTed content type does not match an available data handler, this
564 will also raise an exception.
565
566 =head2 $req->body_parameters
567
568 Returns a reference to a hash containing body (POST) parameters. Values can
569 be either a scalar or an arrayref containing scalars.
570
571     print $c->request->body_parameters->{field};
572     print $c->request->body_parameters->{field}->[0];
573
574 These are the parameters from the POST part of the request, if any.
575
576 B<NOTE> If your POST is multipart, but contains non file upload parts (such
577 as an line part with an alternative encoding or content type) we do our best to
578 try and figure out how the value should be presented.  If there's a specified character
579 set we will use that to decode rather than the default encoding set by the application.
580 However if there are complex headers and we cannot determine
581 the correct way to extra a meaningful value from the upload, in this case any
582 part like this will be represented as an instance of L<Catalyst::Request::PartData>.
583
584 Patches and review of this part of the code welcomed.
585
586 =head2 $req->body_params
587
588 Shortcut for body_parameters.
589
590 =head2 $req->content_encoding
591
592 Shortcut for $req->headers->content_encoding.
593
594 =head2 $req->content_length
595
596 Shortcut for $req->headers->content_length.
597
598 =head2 $req->content_type
599
600 Shortcut for $req->headers->content_type.
601
602 =head2 $req->cookie
603
604 A convenient method to access $req->cookies.
605
606     $cookie  = $c->request->cookie('name');
607     @cookies = $c->request->cookie;
608
609 =cut
610
611 sub cookie {
612     my $self = shift;
613
614     if ( @_ == 0 ) {
615         return keys %{ $self->cookies };
616     }
617
618     if ( @_ == 1 ) {
619
620         my $name = shift;
621
622         unless ( exists $self->cookies->{$name} ) {
623             return undef;
624         }
625
626         return $self->cookies->{$name};
627     }
628 }
629
630 =head2 $req->cookies
631
632 Returns a reference to a hash containing the cookies.
633
634     print $c->request->cookies->{mycookie}->value;
635
636 The cookies in the hash are indexed by name, and the values are L<CGI::Simple::Cookie>
637 objects.
638
639 =head2 $req->header
640
641 Shortcut for $req->headers->header.
642
643 =head2 $req->headers
644
645 Returns an L<HTTP::Headers> object containing the headers for the current request.
646
647     print $c->request->headers->header('X-Catalyst');
648
649 =head2 $req->hostname
650
651 Returns the hostname of the client. Use C<< $req->uri->host >> to get the hostname of the server.
652
653 =head2 $req->input
654
655 Alias for $req->body.
656
657 =head2 $req->query_keywords
658
659 Contains the keywords portion of a query string, when no '=' signs are
660 present.
661
662     http://localhost/path?some+keywords
663
664     $c->request->query_keywords will contain 'some keywords'
665
666 =head2 $req->match
667
668 This contains the matching part of a Regex action. Otherwise
669 it returns the same as 'action', except for default actions,
670 which return an empty string.
671
672 =head2 $req->method
673
674 Contains the request method (C<GET>, C<POST>, C<HEAD>, etc).
675
676 =head2 $req->param
677
678 Returns GET and POST parameters with a CGI.pm-compatible param method. This
679 is an alternative method for accessing parameters in $c->req->parameters.
680
681     $value  = $c->request->param( 'foo' );
682     @values = $c->request->param( 'foo' );
683     @params = $c->request->param;
684
685 Like L<CGI>, and B<unlike> earlier versions of Catalyst, passing multiple
686 arguments to this method, like this:
687
688     $c->request->param( 'foo', 'bar', 'gorch', 'quxx' );
689
690 will set the parameter C<foo> to the multiple values C<bar>, C<gorch> and
691 C<quxx>. Previously this would have added C<bar> as another value to C<foo>
692 (creating it if it didn't exist before), and C<quxx> as another value for
693 C<gorch>.
694
695 B<NOTE> this is considered a legacy interface and care should be taken when
696 using it. C<< scalar $c->req->param( 'foo' ) >> will return only the first
697 C<foo> param even if multiple are present; C<< $c->req->param( 'foo' ) >> will
698 return a list of as many are present, which can have unexpected consequences
699 when writing code of the form:
700
701     $foo->bar(
702         a => 'b',
703         baz => $c->req->param( 'baz' ),
704     );
705
706 If multiple C<baz> parameters are provided this code might corrupt data or
707 cause a hash initialization error. For a more straightforward interface see
708 C<< $c->req->parameters >>.
709
710 B<NOTE> Interfaces like this, which are based on L<CGI> and the C<param> method
711 are known to cause demonstrated exploits. It is highly recommended that you
712 avoid using this method, and migrate existing code away from it.  Here's a
713 whitepaper of the exploit:
714
715 L<http://blog.gerv.net/2014/10/new-class-of-vulnerability-in-perl-web-applications/>
716
717 B<NOTE> Further discussion on IRC indicate that the L<Catalyst> core team from 'back then'
718 were well aware of this hack and this is the main reason we added the new approach to
719 getting parameters in the first place.
720
721 Basically this is an exploit that takes advantage of how L<\param> will do one thing
722 in scalar context and another thing in list context.  This is combined with how Perl
723 chooses to deal with duplicate keys in a hash definition by overwriting the value of
724 existing keys with a new value if the same key shows up again.  Generally you will be
725 vulnerable to this exploit if you are using this method in a direct assignment in a
726 hash, such as with a L<DBIx::Class> create statement.  For example, if you have
727 parameters like:
728
729     user?user=123&foo=a&foo=user&foo=456
730
731 You could end up with extra parameters injected into your method calls:
732
733     $c->model('User')->create({
734       user => $c->req->param('user'),
735       foo => $c->req->param('foo'),
736     });
737
738 Which would look like:
739
740     $c->model('User')->create({
741       user => 123,
742       foo => qw(a user 456),
743     });
744
745 (or to be absolutely clear if you are not seeing it):
746
747     $c->model('User')->create({
748       user => 456,
749       foo => 'a',
750     });
751
752 Possible remediations include scrubbing your parameters with a form validator like
753 L<HTML::FormHandler> or being careful to force scalar context using the scalar
754 keyword:
755
756     $c->model('User')->create({
757       user => scalar($c->req->param('user')),
758       foo => scalar($c->req->param('foo')),
759     });
760
761 Upcoming versions of L<Catalyst> will disable this interface by default and require
762 you to positively enable it should you require it for backwards compatibility reasons.
763
764 =cut
765
766 sub param {
767     my $self = shift;
768
769     if ( @_ == 0 ) {
770         return keys %{ $self->parameters };
771     }
772
773     # If anything in @_ is undef, carp about that, and remove it from
774     # the list;
775     
776     my @params = grep { defined($_) ? 1 : do {carp "You called ->params with an undefined value"; 0} } @_;
777
778     if ( @params == 1 ) {
779
780         defined(my $param = shift @params) ||
781           carp "You called ->params with an undefined value 2";
782
783         unless ( exists $self->parameters->{$param} ) {
784             return wantarray ? () : undef;
785         }
786
787         if ( is_plain_arrayref($self->parameters->{$param}) ) {
788             return (wantarray)
789               ? @{ $self->parameters->{$param} }
790               : $self->parameters->{$param}->[0];
791         }
792         else {
793             return (wantarray)
794               ? ( $self->parameters->{$param} )
795               : $self->parameters->{$param};
796         }
797     }
798     elsif ( @params > 1 ) {
799         my $field = shift @params;
800         $self->parameters->{$field} = [@params];
801     }
802 }
803
804 =head2 $req->parameters
805
806 Returns a reference to a hash containing GET and POST parameters. Values can
807 be either a scalar or an arrayref containing scalars.
808
809     print $c->request->parameters->{field};
810     print $c->request->parameters->{field}->[0];
811
812 This is the combination of C<query_parameters> and C<body_parameters>.
813
814 =head2 $req->params
815
816 Shortcut for $req->parameters.
817
818 =head2 $req->path
819
820 Returns the path, i.e. the part of the URI after $req->base, for the current request.
821
822     http://localhost/path/foo
823
824     $c->request->path will contain 'path/foo'
825
826 =head2 $req->path_info
827
828 Alias for path, added for compatibility with L<CGI>.
829
830 =cut
831
832 sub path {
833     my ( $self, @params ) = @_;
834
835     if (@params) {
836         $self->uri->path(@params);
837         $self->_clear_path;
838     }
839     elsif ( $self->_has_path ) {
840         return $self->_path;
841     }
842     else {
843         my $path     = $self->uri->path;
844         my $location = $self->base->path;
845         $path =~ s/^(\Q$location\E)?//;
846         $path =~ s/^\///;
847         $self->_path($path);
848
849         return $path;
850     }
851 }
852
853 =head2 $req->protocol
854
855 Returns the protocol (HTTP/1.0 or HTTP/1.1) used for the current request.
856
857 =head2 $req->query_parameters
858
859 =head2 $req->query_params
860
861 Returns a reference to a hash containing query string (GET) parameters. Values can
862 be either a scalar or an arrayref containing scalars.
863
864     print $c->request->query_parameters->{field};
865     print $c->request->query_parameters->{field}->[0];
866
867 =head2 $req->read( [$maxlength] )
868
869 Reads a chunk of data from the request body. This method is intended to be
870 used in a while loop, reading $maxlength bytes on every call. $maxlength
871 defaults to the size of the request if not specified.
872
873 =head2 $req->read_chunk(\$buff, $max)
874
875 Reads a chunk.
876
877 You have to set MyApp->config(parse_on_demand => 1) to use this directly.
878
879 =head2 $req->referer
880
881 Shortcut for $req->headers->referer. Returns the referring page.
882
883 =head2 $req->secure
884
885 Returns true or false, indicating whether the connection is secure
886 (https). The reliability of $req->secure may depend on your server
887 configuration; Catalyst relies on PSGI to determine whether or not a
888 request is secure (Catalyst looks at psgi.url_scheme), and different
889 PSGI servers may make this determination in different ways (as by
890 directly passing along information from the server, interpreting any of
891 several HTTP headers, or using heuristics of their own).
892
893 =head2 $req->captures
894
895 Returns a reference to an array containing captured args from chained
896 actions or regex captures.
897
898     my @captures = @{ $c->request->captures };
899
900 =head2 $req->upload
901
902 A convenient method to access $req->uploads.
903
904     $upload  = $c->request->upload('field');
905     @uploads = $c->request->upload('field');
906     @fields  = $c->request->upload;
907
908     for my $upload ( $c->request->upload('field') ) {
909         print $upload->filename;
910     }
911
912 =cut
913
914 sub upload {
915     my $self = shift;
916
917     if ( @_ == 0 ) {
918         return keys %{ $self->uploads };
919     }
920
921     if ( @_ == 1 ) {
922
923         my $upload = shift;
924
925         unless ( exists $self->uploads->{$upload} ) {
926             return wantarray ? () : undef;
927         }
928
929         if ( is_plain_arrayref($self->uploads->{$upload}) ) {
930             return (wantarray)
931               ? @{ $self->uploads->{$upload} }
932               : $self->uploads->{$upload}->[0];
933         }
934         else {
935             return (wantarray)
936               ? ( $self->uploads->{$upload} )
937               : $self->uploads->{$upload};
938         }
939     }
940
941     if ( @_ > 1 ) {
942
943         while ( my ( $field, $upload ) = splice( @_, 0, 2 ) ) {
944
945             if ( exists $self->uploads->{$field} ) {
946                 for ( $self->uploads->{$field} ) {
947                     $_ = [$_] unless is_plain_arrayref($_);
948                     push( @$_, $upload );
949                 }
950             }
951             else {
952                 $self->uploads->{$field} = $upload;
953             }
954         }
955     }
956 }
957
958 =head2 $req->uploads
959
960 Returns a reference to a hash containing uploads. Values can be either a
961 L<Catalyst::Request::Upload> object, or an arrayref of
962 L<Catalyst::Request::Upload> objects.
963
964     my $upload = $c->request->uploads->{field};
965     my $upload = $c->request->uploads->{field}->[0];
966
967 =head2 $req->uri
968
969 Returns a L<URI> object for the current request. Stringifies to the URI text.
970
971 =head2 $req->mangle_params( { key => 'value' }, $appendmode);
972
973 Returns a hashref of parameters stemming from the current request's params,
974 plus the ones supplied.  Keys for which no current param exists will be
975 added, keys with undefined values will be removed and keys with existing
976 params will be replaced.  Note that you can supply a true value as the final
977 argument to change behavior with regards to existing parameters, appending
978 values rather than replacing them.
979
980 A quick example:
981
982   # URI query params foo=1
983   my $hashref = $req->mangle_params({ foo => 2 });
984   # Result is query params of foo=2
985
986 versus append mode:
987
988   # URI query params foo=1
989   my $hashref = $req->mangle_params({ foo => 2 }, 1);
990   # Result is query params of foo=1&foo=2
991
992 This is the code behind C<uri_with>.
993
994 =cut
995
996 sub mangle_params {
997     my ($self, $args, $append) = @_;
998
999     carp('No arguments passed to mangle_params()') unless $args;
1000
1001     foreach my $value ( values %$args ) {
1002         next unless defined $value;
1003         for ( is_plain_arrayref($value) ? @$value : $value ) {
1004             $_ = "$_";
1005             #      utf8::encode($_);
1006         }
1007     };
1008
1009     my %params = %{ $self->uri->query_form_hash };
1010     foreach my $key (keys %{ $args }) {
1011         my $val = $args->{$key};
1012         if(defined($val)) {
1013
1014             if($append && exists($params{$key})) {
1015
1016                 # This little bit of heaven handles appending a new value onto
1017                 # an existing one regardless if the existing value is an array
1018                 # or not, and regardless if the new value is an array or not
1019                 $params{$key} = [
1020                     is_plain_arrayref($params{$key}) ? @{ $params{$key} } : $params{$key},
1021                     is_plain_arrayref($val) ? @{ $val } : $val
1022                 ];
1023
1024             } else {
1025                 $params{$key} = $val;
1026             }
1027         } else {
1028
1029             # If the param wasn't defined then we delete it.
1030             delete($params{$key});
1031         }
1032     }
1033
1034
1035     return \%params;
1036 }
1037
1038 =head2 $req->uri_with( { key => 'value' } );
1039
1040 Returns a rewritten URI object for the current request. Key/value pairs
1041 passed in will override existing parameters. You can remove an existing
1042 parameter by passing in an undef value. Unmodified pairs will be
1043 preserved.
1044
1045 You may also pass an optional second parameter that puts C<uri_with> into
1046 append mode:
1047
1048   $req->uri_with( { key => 'value' }, { mode => 'append' } );
1049
1050 See C<mangle_params> for an explanation of this behavior.
1051
1052 =cut
1053
1054 sub uri_with {
1055     my( $self, $args, $behavior) = @_;
1056
1057     carp( 'No arguments passed to uri_with()' ) unless $args;
1058
1059     my $append = 0;
1060     if(is_plain_hashref($behavior) && defined($behavior->{mode}) && ($behavior->{mode} eq 'append')) {
1061         $append = 1;
1062     }
1063
1064     my $params = $self->mangle_params($args, $append);
1065
1066     my $uri = $self->uri->clone;
1067     $uri->query_form($params);
1068
1069     return $uri;
1070 }
1071
1072 =head2 $req->remote_user
1073
1074 Returns the value of the C<REMOTE_USER> environment variable.
1075
1076 =head2 $req->user_agent
1077
1078 Shortcut to $req->headers->user_agent. Returns the user agent (browser)
1079 version string.
1080
1081 =head2 $req->io_fh
1082
1083 Returns a psgix.io bidirectional socket, if your server supports one.  Used for
1084 when you want to jailbreak out of PSGI and handle bidirectional client server
1085 communication manually, such as when you are using cometd or websockets.
1086
1087 =head1 SETUP METHODS
1088
1089 You should never need to call these yourself in application code,
1090 however they are useful if extending Catalyst by applying a request role.
1091
1092 =head2 $self->prepare_headers()
1093
1094 Sets up the C<< $res->headers >> accessor.
1095
1096 =head2 $self->prepare_body()
1097
1098 Sets up the body using L<HTTP::Body>
1099
1100 =head2 $self->prepare_body_chunk()
1101
1102 Add a chunk to the request body.
1103
1104 =head2 $self->prepare_body_parameters()
1105
1106 Sets up parameters from body.
1107
1108 =head2 $self->prepare_cookies()
1109
1110 Parse cookies from header. Sets up a L<CGI::Simple::Cookie> object.
1111
1112 =head2 $self->prepare_connection()
1113
1114 Sets up various fields in the request like the local and remote addresses,
1115 request method, hostname requested etc.
1116
1117 =head2 $self->prepare_parameters()
1118
1119 Ensures that the body has been parsed, then builds the parameters, which are
1120 combined from those in the request and those in the body.
1121
1122 If parameters have already been set will clear the parameters and build them again.
1123
1124 =head2 $self->env
1125
1126 Access to the raw PSGI env.  
1127
1128 =head2 meta
1129
1130 Provided by Moose
1131
1132 =head1 AUTHORS
1133
1134 Catalyst Contributors, see Catalyst.pm
1135
1136 =head1 COPYRIGHT
1137
1138 This library is free software. You can redistribute it and/or modify
1139 it under the same terms as Perl itself.
1140
1141 =cut
1142
1143 __PACKAGE__->meta->make_immutable;
1144
1145 1;