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