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