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