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