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