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