Fixed "its" vs "it's"
[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;
b4ca0ee8 10
059c085b 11use Moose;
12
6802c884 13use namespace::clean -except => 'meta';
14
b99ff5d8 15with 'MooseX::Emulate::Class::Accessor::Fast';
16
5fb12dbb 17has action => (is => 'rw');
18has address => (is => 'rw');
19has arguments => (is => 'rw', default => sub { [] });
20has cookies => (is => 'rw', default => sub { {} });
21has query_keywords => (is => 'rw');
22has match => (is => 'rw');
23has method => (is => 'rw');
24has protocol => (is => 'rw');
059c085b 25has query_parameters => (is => 'rw', default => sub { {} });
5fb12dbb 26has secure => (is => 'rw', default => 0);
27has captures => (is => 'rw', default => sub { [] });
6cb9e383 28has uri => (is => 'rw', predicate => 'has_uri');
f263fa9a 29has user => (is => 'rw');
5fb12dbb 30has headers => (
e5ecd5bc 31 is => 'rw',
059c085b 32 isa => 'HTTP::Headers',
33 handles => [qw(content_encoding content_length content_type header referer user_agent)],
6680c772 34 default => sub { HTTP::Headers->new() },
35 required => 1,
36 lazy => 1,
059c085b 37);
38
39has _context => (
40 is => 'rw',
41 weak_ref => 1,
0fc2d522 42 handles => ['read'],
02570318 43 clearer => '_clear_context',
059c085b 44);
45
46has body_parameters => (
5fb12dbb 47 is => 'rw',
48 required => 1,
49 lazy => 1,
50 default => sub { {} },
fc7ec1d9 51);
52
059c085b 53has uploads => (
5fb12dbb 54 is => 'rw',
55 required => 1,
5fb12dbb 56 default => sub { {} },
059c085b 57);
58
059c085b 59has parameters => (
60 is => 'rw',
61 required => 1,
62 lazy => 1,
63 default => sub { {} },
64);
65
341620d5 66# TODO:
67# - Can we lose the before modifiers which just call prepare_body ?
68# they are wasteful, slow us down and feel cluttery.
69
70# Can we make _body an attribute, have the rest of
71# these lazy build from there and kill all the direct hash access
72# in Catalyst.pm and Engine.pm?
73
74before $_ => sub {
75 my ($self) = @_;
76 my $context = $self->_context || return;
77 $context->prepare_body;
78} for qw/parameters body_parameters/;
79
e99ec2dc 80around parameters => sub {
81 my ($orig, $self, $params) = @_;
82 if ($params) {
83 if ( !ref $params ) {
84 $self->_context->log->warn(
85 "Attempt to retrieve '$params' with req->params(), " .
86 "you probably meant to call req->param('$params')"
87 );
88 $params = undef;
89 }
90 return $self->$orig($params);
91 }
92 $self->$orig();
059c085b 93};
94
95has base => (
5fb12dbb 96 is => 'rw',
97 required => 1,
98 lazy => 1,
99 default => sub {
059c085b 100 my $self = shift;
6cb9e383 101 return $self->path if $self->has_uri;
059c085b 102 },
103);
104
069355da 105has _body => (
0f56bbcf 106 is => 'rw', clearer => '_clear_body', predicate => '_has_body',
059c085b 107);
610bc6ec 108# Eugh, ugly. Should just be able to rename accessor methods to 'body'
109# and provide a custom reader..
110sub body {
111 my $self = shift;
059c085b 112 $self->_context->prepare_body();
610bc6ec 113 $self->_body(@_) if scalar @_;
114 return blessed $self->_body ? $self->_body->body : $self->_body;
115}
059c085b 116
117has hostname => (
118 is => 'rw',
119 required => 1,
120 lazy => 1,
121 default => sub {
122 my ($self) = @_;
8fc0d39e 123 gethostbyaddr( inet_aton( $self->address ), AF_INET ) || 'localhost'
059c085b 124 },
125);
126
02570318 127has _path => ( is => 'rw', predicate => '_has_path', clearer => '_clear_path' );
128
059c085b 129sub args { shift->arguments(@_) }
130sub body_params { shift->body_parameters(@_) }
131sub input { shift->body(@_) }
132sub params { shift->parameters(@_) }
133sub query_params { shift->query_parameters(@_) }
134sub path_info { shift->path(@_) }
135sub snippets { shift->captures(@_) }
f7e4e231 136
fc7ec1d9 137=head1 NAME
138
3e19f4f6 139Catalyst::Request - provides information about the current client request
fc7ec1d9 140
141=head1 SYNOPSIS
142
b22c6668 143 $req = $c->request;
144 $req->action;
145 $req->address;
b22c6668 146 $req->arguments;
3e19f4f6 147 $req->args;
b22c6668 148 $req->base;
06e1b616 149 $req->body;
fbcc39ad 150 $req->body_parameters;
b5176d9e 151 $req->content_encoding;
152 $req->content_length;
153 $req->content_type;
b77e7869 154 $req->cookie;
b22c6668 155 $req->cookies;
b5176d9e 156 $req->header;
b22c6668 157 $req->headers;
158 $req->hostname;
61bacdcc 159 $req->input;
3b4d1251 160 $req->query_keywords;
b22c6668 161 $req->match;
162 $req->method;
e7c0c583 163 $req->param;
e7c0c583 164 $req->parameters;
3e19f4f6 165 $req->params;
b22c6668 166 $req->path;
bfde09a2 167 $req->protocol;
fbcc39ad 168 $req->query_parameters;
169 $req->read;
b5176d9e 170 $req->referer;
bfde09a2 171 $req->secure;
2982e768 172 $req->captures; # previously knows as snippets
e7c0c583 173 $req->upload;
b22c6668 174 $req->uploads;
77d12cae 175 $req->uri;
7ce7ca2e 176 $req->user;
66294129 177 $req->user_agent;
b22c6668 178
3e22baa5 179See also L<Catalyst>, L<Catalyst::Request::Upload>.
fc7ec1d9 180
181=head1 DESCRIPTION
182
3e19f4f6 183This is the Catalyst Request class, which provides an interface to data for the
184current client request. The request object is prepared by L<Catalyst::Engine>,
185thus hiding the details of the particular engine implementation.
b22c6668 186
187=head1 METHODS
fc7ec1d9 188
b5ecfcf0 189=head2 $req->action
fc7ec1d9 190
aae8d418 191[DEPRECATED] Returns the name of the requested action.
192
193
194Use C<< $c->action >> instead (which returns a
195L<Catalyst::Action|Catalyst::Action> object).
fc7ec1d9 196
b5ecfcf0 197=head2 $req->address
0556eb49 198
3e19f4f6 199Returns the IP address of the client.
61b1e958 200
b5ecfcf0 201=head2 $req->arguments
61b1e958 202
b22c6668 203Returns a reference to an array containing the arguments.
fc7ec1d9 204
205 print $c->request->arguments->[0];
206
c436c1e8 207For example, if your action was
208
85d9fce6 209 package MyApp::C::Foo;
210
211 sub moose : Local {
212 ...
213 }
c436c1e8 214
3e19f4f6 215and the URI for the request was C<http://.../foo/moose/bah>, the string C<bah>
c436c1e8 216would be the first and only argument.
217
8f58057d 218Arguments just get passed through and B<don't> get unescaped automatically, so
219you should do that explicitly.
220
b5ecfcf0 221=head2 $req->args
3e19f4f6 222
223Shortcut for arguments.
224
b5ecfcf0 225=head2 $req->base
fc7ec1d9 226
328f225e 227Contains the URI base. This will always have a trailing slash. Note that the
228URI scheme (eg., http vs. https) must be determined through heuristics;
229depending on your server configuration, it may be incorrect. See $req->secure
230for more info.
c436c1e8 231
3e19f4f6 232If your application was queried with the URI
233C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
fc7ec1d9 234
b5ecfcf0 235=head2 $req->body
06e1b616 236
3e19f4f6 237Returns the message body of the request, unless Content-Type is
e060fe05 238C<application/x-www-form-urlencoded> or C<multipart/form-data>.
239
b5ecfcf0 240=head2 $req->body_parameters
fbcc39ad 241
3e19f4f6 242Returns a reference to a hash containing body (POST) parameters. Values can
fbcc39ad 243be either a scalar or an arrayref containing scalars.
244
245 print $c->request->body_parameters->{field};
246 print $c->request->body_parameters->{field}->[0];
c436c1e8 247
d631b5f9 248These are the parameters from the POST part of the request, if any.
e5ecd5bc 249
b5ecfcf0 250=head2 $req->body_params
fbcc39ad 251
3e19f4f6 252Shortcut for body_parameters.
fbcc39ad 253
b5ecfcf0 254=head2 $req->content_encoding
b5176d9e 255
3e19f4f6 256Shortcut for $req->headers->content_encoding.
b5176d9e 257
b5ecfcf0 258=head2 $req->content_length
b5176d9e 259
3e19f4f6 260Shortcut for $req->headers->content_length.
b5176d9e 261
b5ecfcf0 262=head2 $req->content_type
b5176d9e 263
3e19f4f6 264Shortcut for $req->headers->content_type.
b5176d9e 265
b5ecfcf0 266=head2 $req->cookie
3ad654e0 267
3e19f4f6 268A convenient method to access $req->cookies.
3ad654e0 269
270 $cookie = $c->request->cookie('name');
271 @cookies = $c->request->cookie;
272
273=cut
274
275sub cookie {
276 my $self = shift;
277
278 if ( @_ == 0 ) {
b77e7869 279 return keys %{ $self->cookies };
3ad654e0 280 }
281
282 if ( @_ == 1 ) {
283
284 my $name = shift;
285
b77e7869 286 unless ( exists $self->cookies->{$name} ) {
3ad654e0 287 return undef;
288 }
fbcc39ad 289
b77e7869 290 return $self->cookies->{$name};
3ad654e0 291 }
292}
293
b5ecfcf0 294=head2 $req->cookies
fc7ec1d9 295
b22c6668 296Returns a reference to a hash containing the cookies.
fc7ec1d9 297
298 print $c->request->cookies->{mycookie}->value;
299
3e19f4f6 300The cookies in the hash are indexed by name, and the values are L<CGI::Cookie>
c436c1e8 301objects.
302
b5ecfcf0 303=head2 $req->header
b5176d9e 304
3e19f4f6 305Shortcut for $req->headers->header.
b5176d9e 306
b5ecfcf0 307=head2 $req->headers
fc7ec1d9 308
3e19f4f6 309Returns an L<HTTP::Headers> object containing the headers for the current request.
fc7ec1d9 310
311 print $c->request->headers->header('X-Catalyst');
312
b5ecfcf0 313=head2 $req->hostname
0556eb49 314
3e19f4f6 315Returns the hostname of the client.
e5ecd5bc 316
b5ecfcf0 317=head2 $req->input
61bacdcc 318
3e19f4f6 319Alias for $req->body.
61bacdcc 320
3b4d1251 321=head2 $req->query_keywords
322
323Contains the keywords portion of a query string, when no '=' signs are
324present.
325
326 http://localhost/path?some+keywords
ac5c933b 327
3b4d1251 328 $c->request->query_keywords will contain 'some keywords'
329
b5ecfcf0 330=head2 $req->match
fc7ec1d9 331
3e19f4f6 332This contains the matching part of a Regex action. Otherwise
2c83fd5a 333it returns the same as 'action', except for default actions,
334which return an empty string.
fc7ec1d9 335
b5ecfcf0 336=head2 $req->method
b5176d9e 337
338Contains the request method (C<GET>, C<POST>, C<HEAD>, etc).
339
b5ecfcf0 340=head2 $req->param
e7c0c583 341
ac5c933b 342Returns GET and POST parameters with a CGI.pm-compatible param method. This
3e19f4f6 343is an alternative method for accessing parameters in $c->req->parameters.
e7c0c583 344
a82c2894 345 $value = $c->request->param( 'foo' );
346 @values = $c->request->param( 'foo' );
e7c0c583 347 @params = $c->request->param;
348
3e705254 349Like L<CGI>, and B<unlike> earlier versions of Catalyst, passing multiple
a82c2894 350arguments to this method, like this:
351
85d9fce6 352 $c->request->param( 'foo', 'bar', 'gorch', 'quxx' );
a82c2894 353
354will set the parameter C<foo> to the multiple values C<bar>, C<gorch> and
355C<quxx>. Previously this would have added C<bar> as another value to C<foo>
3e19f4f6 356(creating it if it didn't exist before), and C<quxx> as another value for
357C<gorch>.
a82c2894 358
e7c0c583 359=cut
360
361sub param {
362 my $self = shift;
363
364 if ( @_ == 0 ) {
365 return keys %{ $self->parameters };
366 }
367
bfde09a2 368 if ( @_ == 1 ) {
e7c0c583 369
bfde09a2 370 my $param = shift;
6bd2b72c 371
bfde09a2 372 unless ( exists $self->parameters->{$param} ) {
373 return wantarray ? () : undef;
374 }
375
376 if ( ref $self->parameters->{$param} eq 'ARRAY' ) {
377 return (wantarray)
378 ? @{ $self->parameters->{$param} }
379 : $self->parameters->{$param}->[0];
380 }
381 else {
382 return (wantarray)
383 ? ( $self->parameters->{$param} )
384 : $self->parameters->{$param};
385 }
d7945f32 386 }
a82c2894 387 elsif ( @_ > 1 ) {
388 my $field = shift;
389 $self->parameters->{$field} = [@_];
d7945f32 390 }
e7c0c583 391}
b5176d9e 392
b5ecfcf0 393=head2 $req->parameters
61b1e958 394
3e19f4f6 395Returns a reference to a hash containing GET and POST parameters. Values can
d08ced28 396be either a scalar or an arrayref containing scalars.
fc7ec1d9 397
e7c0c583 398 print $c->request->parameters->{field};
399 print $c->request->parameters->{field}->[0];
fc7ec1d9 400
c436c1e8 401This is the combination of C<query_parameters> and C<body_parameters>.
402
b5ecfcf0 403=head2 $req->params
3e19f4f6 404
405Shortcut for $req->parameters.
406
b5ecfcf0 407=head2 $req->path
fc7ec1d9 408
3e19f4f6 409Returns the path, i.e. the part of the URI after $req->base, for the current request.
fc7ec1d9 410
b5ecfcf0 411=head2 $req->path_info
fbcc39ad 412
10011c19 413Alias for path, added for compatibility with L<CGI>.
fbcc39ad 414
415=cut
416
417sub path {
02fb5d78 418 my ( $self, @params ) = @_;
4f5ebacd 419
02fb5d78 420 if (@params) {
421 $self->uri->path(@params);
02570318 422 $self->_clear_path;
fbcc39ad 423 }
02570318 424 elsif ( $self->_has_path ) {
425 return $self->_path;
e561386f 426 }
02fb5d78 427 else {
428 my $path = $self->uri->path;
429 my $location = $self->base->path;
430 $path =~ s/^(\Q$location\E)?//;
431 $path =~ s/^\///;
02570318 432 $self->_path($path);
fbcc39ad 433
02fb5d78 434 return $path;
435 }
fbcc39ad 436}
437
b5ecfcf0 438=head2 $req->protocol
bfde09a2 439
3e19f4f6 440Returns the protocol (HTTP/1.0 or HTTP/1.1) used for the current request.
bfde09a2 441
b5ecfcf0 442=head2 $req->query_parameters
fbcc39ad 443
def54ce2 444=head2 $req->query_params
445
3e19f4f6 446Returns a reference to a hash containing query string (GET) parameters. Values can
fbcc39ad 447be either a scalar or an arrayref containing scalars.
448
449 print $c->request->query_parameters->{field};
450 print $c->request->query_parameters->{field}->[0];
ac5c933b 451
b5ecfcf0 452=head2 $req->read( [$maxlength] )
fbcc39ad 453
3e19f4f6 454Reads a chunk of data from the request body. This method is intended to be
455used in a while loop, reading $maxlength bytes on every call. $maxlength
fbcc39ad 456defaults to the size of the request if not specified.
457
458You have to set MyApp->config->{parse_on_demand} to use this directly.
459
b5ecfcf0 460=head2 $req->referer
fc7ec1d9 461
3e19f4f6 462Shortcut for $req->headers->referer. Returns the referring page.
fc7ec1d9 463
b5ecfcf0 464=head2 $req->secure
bfde09a2 465
328f225e 466Returns true or false, indicating whether the connection is secure
467(https). Note that the URI scheme (eg., http vs. https) must be determined
468through heuristics, and therefore the reliablity of $req->secure will depend
469on your server configuration. If you are serving secure pages on the standard
470SSL port (443) and/or setting the HTTPS environment variable, $req->secure
471should be valid.
bfde09a2 472
2982e768 473=head2 $req->captures
474
5c6a56e0 475Returns a reference to an array containing captured args from chained
476actions or regex captures.
fc7ec1d9 477
2982e768 478 my @captures = @{ $c->request->captures };
479
480=head2 $req->snippets
fc7ec1d9 481
10011c19 482C<captures> used to be called snippets. This is still available for backwards
2982e768 483compatibility, but is considered deprecated.
fc7ec1d9 484
b5ecfcf0 485=head2 $req->upload
e7c0c583 486
3e19f4f6 487A convenient method to access $req->uploads.
e7c0c583 488
489 $upload = $c->request->upload('field');
490 @uploads = $c->request->upload('field');
491 @fields = $c->request->upload;
bfde09a2 492
e7c0c583 493 for my $upload ( $c->request->upload('field') ) {
146554c5 494 print $upload->filename;
e7c0c583 495 }
496
497=cut
498
499sub upload {
500 my $self = shift;
501
502 if ( @_ == 0 ) {
503 return keys %{ $self->uploads };
504 }
505
bfde09a2 506 if ( @_ == 1 ) {
e7c0c583 507
bfde09a2 508 my $upload = shift;
509
510 unless ( exists $self->uploads->{$upload} ) {
511 return wantarray ? () : undef;
512 }
6bd2b72c 513
bfde09a2 514 if ( ref $self->uploads->{$upload} eq 'ARRAY' ) {
515 return (wantarray)
516 ? @{ $self->uploads->{$upload} }
517 : $self->uploads->{$upload}->[0];
518 }
519 else {
520 return (wantarray)
fbcc39ad 521 ? ( $self->uploads->{$upload} )
522 : $self->uploads->{$upload};
bfde09a2 523 }
d7945f32 524 }
bfde09a2 525
a4f5c51e 526 if ( @_ > 1 ) {
bfde09a2 527
528 while ( my ( $field, $upload ) = splice( @_, 0, 2 ) ) {
529
530 if ( exists $self->uploads->{$field} ) {
531 for ( $self->uploads->{$field} ) {
532 $_ = [$_] unless ref($_) eq "ARRAY";
533 push( @$_, $upload );
534 }
535 }
536 else {
537 $self->uploads->{$field} = $upload;
538 }
539 }
e7c0c583 540 }
541}
542
b5ecfcf0 543=head2 $req->uploads
fc7ec1d9 544
bfde09a2 545Returns a reference to a hash containing uploads. Values can be either a
ac5c933b 546L<Catalyst::Request::Upload> object, or an arrayref of
84e7aa89 547L<Catalyst::Request::Upload> objects.
e7c0c583 548
549 my $upload = $c->request->uploads->{field};
550 my $upload = $c->request->uploads->{field}->[0];
551
b5ecfcf0 552=head2 $req->uri
fbcc39ad 553
3e19f4f6 554Returns a URI object for the current request. Stringifies to the URI text.
fbcc39ad 555
bd917b94 556=head2 $req->uri_with( { key => 'value' } );
557
3338e8ce 558Returns a rewritten URI object for the current request. Key/value pairs
2f381252 559passed in will override existing parameters. You can remove an existing
560parameter by passing in an undef value. Unmodified pairs will be
3338e8ce 561preserved.
bd917b94 562
563=cut
564
565sub uri_with {
566 my( $self, $args ) = @_;
ac5c933b 567
bd917b94 568 carp( 'No arguments passed to uri_with()' ) unless $args;
fbb513f7 569
2f381252 570 foreach my $value ( values %$args ) {
d0f0fcf6 571 next unless defined $value;
fbb513f7 572 for ( ref $value eq 'ARRAY' ? @$value : $value ) {
573 $_ = "$_";
7066a4d5 574 utf8::encode( $_ ) if utf8::is_utf8($_);
fc42a730 575 }
fc42a730 576 };
ac5c933b 577
2f381252 578 my $uri = $self->uri->clone;
579 my %query = ( %{ $uri->query_form_hash }, %$args );
580
bd917b94 581 $uri->query_form( {
2f381252 582 # remove undef values
583 map { defined $query{ $_ } ? ( $_ => $query{ $_ } ) : () } keys %query
bd917b94 584 } );
585 return $uri;
586}
587
b5ecfcf0 588=head2 $req->user
7ce7ca2e 589
3e19f4f6 590Returns the currently logged in user. Deprecated. The method recommended for
591newer plugins is $c->user.
7ce7ca2e 592
b5ecfcf0 593=head2 $req->user_agent
b5176d9e 594
3e19f4f6 595Shortcut to $req->headers->user_agent. Returns the user agent (browser)
596version string.
b5176d9e 597
059c085b 598=head2 meta
599
600Provided by Moose
601
3e19f4f6 602=head1 AUTHORS
fc7ec1d9 603
2f381252 604Catalyst Contributors, see Catalyst.pm
fc7ec1d9 605
606=head1 COPYRIGHT
607
e7c0c583 608This program is free software, you can redistribute it and/or modify
61b1e958 609it under the same terms as Perl itself.
fc7ec1d9 610
611=cut
612
e5ecd5bc 613__PACKAGE__->meta->make_immutable;
614
fc7ec1d9 6151;