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