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