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