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