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