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