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