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