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