1 package Catalyst::Request;
3 use IO::Socket qw[AF_INET inet_aton];
13 use namespace::clean -except => 'meta';
15 with 'MooseX::Emulate::Class::Accessor::Fast';
17 has env => (is => 'ro', writer => '_set_env');
18 # XXX Deprecated crap here - warn?
19 has action => (is => 'rw');
20 # XXX: Deprecated in docs ages ago (2006), deprecated with warning in 5.8000 due
21 # to confusion between Engines and Plugin::Authentication. Remove in 5.8100?
22 has user => (is => 'rw');
23 sub snippets { shift->captures(@_) }
25 has _read_position => (
28 writer => '_set_read_position',
36 $self->header('Content-Length') || 0;
41 has address => (is => 'rw');
42 has arguments => (is => 'rw', default => sub { [] });
43 has cookies => (is => 'ro', builder => 'prepare_cookies', lazy => 1);
48 if ( my $header = $self->header('Cookie') ) {
49 return { CGI::Simple::Cookie->parse($header) };
54 has query_keywords => (is => 'rw');
55 has match => (is => 'rw');
56 has method => (is => 'rw');
57 has protocol => (is => 'rw');
58 has query_parameters => (is => 'rw', default => sub { {} });
59 has secure => (is => 'rw', default => 0);
60 has captures => (is => 'rw', default => sub { [] });
61 has uri => (is => 'rw', predicate => 'has_uri');
62 has remote_user => (is => 'rw');
65 isa => 'HTTP::Headers',
66 handles => [qw(content_encoding content_length content_type header referer user_agent)],
67 builder => 'prepare_headers',
75 my $headers = HTTP::Headers->new();
77 for my $header (keys %{ $env }) {
78 next unless $header =~ /^(HTTP|CONTENT|COOKIE)/i;
79 (my $field = $header) =~ s/^HTTPS?_//;
81 $headers->header($field => $env->{$header});
92 # Amount of data to read from input on each pass
93 our $CHUNKSIZE = 64 * 1024;
96 my ($self, $maxlength) = @_;
97 my $remaining = $self->_read_length - $self->_read_position;
98 $maxlength ||= $CHUNKSIZE;
100 # Are we done reading?
101 if ( $remaining <= 0 ) {
105 my $readlen = ( $remaining > $maxlength ) ? $maxlength : $remaining;
106 my $rc = $self->read_chunk( my $buffer, $readlen );
108 if (0 == $rc) { # Nothing more to read even though Content-Length
109 # said there should be.
112 $self->_set_read_position( $self->_read_position + $rc );
116 Catalyst::Exception->throw(
117 message => "Unknown error reading input: $!" );
123 return $self->env->{'psgi.input'}->read(@_);
126 has body_parameters => (
130 default => sub { {} },
136 default => sub { {} },
142 builder => 'prepare_parameters',
146 # - Can we lose the before modifiers which just call prepare_body ?
147 # they are wasteful, slow us down and feel cluttery.
149 # Can we make _body an attribute, have the rest of
150 # these lazy build from there and kill all the direct hash access
151 # in Catalyst.pm and Engine.pm?
153 sub prepare_parameters {
158 my $body_parameters = $self->body_parameters;
159 my $query_parameters = $self->query_parameters;
160 # We copy, no references
161 foreach my $name (keys %$query_parameters) {
162 my $param = $query_parameters->{$name};
163 $parameters->{$name} = ref $param eq 'ARRAY' ? [ @$param ] : $param;
166 # Merge query and body parameters
167 foreach my $name (keys %$body_parameters) {
168 my $param = $body_parameters->{$name};
169 my @values = ref $param eq 'ARRAY' ? @$param : ($param);
170 if ( my $existing = $parameters->{$name} ) {
171 unshift(@values, (ref $existing eq 'ARRAY' ? @$existing : $existing));
173 $parameters->{$name} = @values > 1 ? \@values : $values[0];
178 before body_parameters => sub {
181 $self->prepare_body_parameters;
186 predicate => '_has_uploadtmp',
192 if ( my $length = $self->_read_length ) {
193 unless ( $self->_body ) {
194 my $type = $self->header('Content-Type');
195 $self->_body(HTTP::Body->new( $type, $length ));
196 $self->_body->cleanup(1); # Make extra sure!
197 $self->_body->tmpdir( $self->_uploadtmp )
198 if $self->_has_uploadtmp;
201 # Check for definedness as you could read '0'
202 while ( defined ( my $buffer = $self->read() ) ) {
203 $self->prepare_body_chunk($buffer);
206 # paranoia against wrong Content-Length header
207 my $remaining = $length - $self->_read_position;
208 if ( $remaining > 0 ) {
209 Catalyst::Exception->throw(
210 "Wrong Content-Length value: $length" );
214 # Defined but will cause all body code to be skipped
219 sub prepare_body_chunk {
220 my ( $self, $chunk ) = @_;
222 $self->_body->add($chunk);
225 sub prepare_body_parameters {
228 return unless $self->_body;
230 $self->{body_parameters} = $self->_body->param; # FIXME!! Recursion here.
233 sub prepare_connection {
236 my $env = $self->env;
238 $self->address( $env->{REMOTE_ADDR} );
239 $self->hostname( $env->{REMOTE_HOST} )
240 if exists $env->{REMOTE_HOST};
241 $self->protocol( $env->{SERVER_PROTOCOL} );
242 $self->remote_user( $env->{REMOTE_USER} );
243 $self->method( $env->{REQUEST_METHOD} );
244 $self->secure( $env->{'psgi.url_scheme'} eq 'https' ? 1 : 0 );
247 # XXX - FIXME - method is here now, move this crap...
248 around parameters => sub {
249 my ($orig, $self, $params) = @_;
251 if ( !ref $params ) {
253 "Attempt to retrieve '$params' with req->params(), " .
254 "you probably meant to call req->param('$params')"
258 return $self->$orig($params);
269 return $self->path if $self->has_uri;
274 is => 'rw', clearer => '_clear_body', predicate => '_has_body',
276 # Eugh, ugly. Should just be able to rename accessor methods to 'body'
277 # and provide a custom reader..
280 $self->prepare_body();
281 croak 'body is a reader' if scalar @_;
282 return blessed $self->_body ? $self->_body->body : $self->_body;
291 gethostbyaddr( inet_aton( $self->address ), AF_INET ) || $self->address
295 has _path => ( is => 'rw', predicate => '_has_path', clearer => '_clear_path' );
297 sub args { shift->arguments(@_) }
298 sub body_params { shift->body_parameters(@_) }
299 sub input { shift->body(@_) }
300 sub params { shift->parameters(@_) }
301 sub query_params { shift->query_parameters(@_) }
302 sub path_info { shift->path(@_) }
304 =for stopwords param params
308 Catalyst::Request - provides information about the current client request
313 $req->address eq "127.0.0.1";
318 $req->body_parameters;
319 $req->content_encoding;
320 $req->content_length;
328 $req->query_keywords;
336 $req->query_parameters;
347 See also L<Catalyst>, L<Catalyst::Request::Upload>.
351 This is the Catalyst Request class, which provides an interface to data for the
352 current client request. The request object is prepared by L<Catalyst::Engine>,
353 thus hiding the details of the particular engine implementation.
359 Returns the IP address of the client.
361 =head2 $req->arguments
363 Returns a reference to an array containing the arguments.
365 print $c->request->arguments->[0];
367 For example, if your action was
369 package MyApp::Controller::Foo;
375 and the URI for the request was C<http://.../foo/moose/bah>, the string C<bah>
376 would be the first and only argument.
378 Arguments get automatically URI-unescaped for you.
382 Shortcut for L</arguments>.
386 Contains the URI base. This will always have a trailing slash. Note that the
387 URI scheme (e.g., http vs. https) must be determined through heuristics;
388 depending on your server configuration, it may be incorrect. See $req->secure
391 If your application was queried with the URI
392 C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
396 Returns the message body of the request, as returned by L<HTTP::Body>: a string,
397 unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
398 C<multipart/form-data>, in which case a L<File::Temp> object is returned.
400 =head2 $req->body_parameters
402 Returns a reference to a hash containing body (POST) parameters. Values can
403 be either a scalar or an arrayref containing scalars.
405 print $c->request->body_parameters->{field};
406 print $c->request->body_parameters->{field}->[0];
408 These are the parameters from the POST part of the request, if any.
410 =head2 $req->body_params
412 Shortcut for body_parameters.
414 =head2 $req->content_encoding
416 Shortcut for $req->headers->content_encoding.
418 =head2 $req->content_length
420 Shortcut for $req->headers->content_length.
422 =head2 $req->content_type
424 Shortcut for $req->headers->content_type.
428 A convenient method to access $req->cookies.
430 $cookie = $c->request->cookie('name');
431 @cookies = $c->request->cookie;
439 return keys %{ $self->cookies };
446 unless ( exists $self->cookies->{$name} ) {
450 return $self->cookies->{$name};
456 Returns a reference to a hash containing the cookies.
458 print $c->request->cookies->{mycookie}->value;
460 The cookies in the hash are indexed by name, and the values are L<CGI::Simple::Cookie>
465 Shortcut for $req->headers->header.
469 Returns an L<HTTP::Headers> object containing the headers for the current request.
471 print $c->request->headers->header('X-Catalyst');
473 =head2 $req->hostname
475 Returns the hostname of the client. Use C<< $req->uri->host >> to get the hostname of the server.
479 Alias for $req->body.
481 =head2 $req->query_keywords
483 Contains the keywords portion of a query string, when no '=' signs are
486 http://localhost/path?some+keywords
488 $c->request->query_keywords will contain 'some keywords'
492 This contains the matching part of a Regex action. Otherwise
493 it returns the same as 'action', except for default actions,
494 which return an empty string.
498 Contains the request method (C<GET>, C<POST>, C<HEAD>, etc).
502 Returns GET and POST parameters with a CGI.pm-compatible param method. This
503 is an alternative method for accessing parameters in $c->req->parameters.
505 $value = $c->request->param( 'foo' );
506 @values = $c->request->param( 'foo' );
507 @params = $c->request->param;
509 Like L<CGI>, and B<unlike> earlier versions of Catalyst, passing multiple
510 arguments to this method, like this:
512 $c->request->param( 'foo', 'bar', 'gorch', 'quxx' );
514 will set the parameter C<foo> to the multiple values C<bar>, C<gorch> and
515 C<quxx>. Previously this would have added C<bar> as another value to C<foo>
516 (creating it if it didn't exist before), and C<quxx> as another value for
519 B<NOTE> this is considered a legacy interface and care should be taken when
520 using it. C<< scalar $c->req->param( 'foo' ) >> will return only the first
521 C<foo> param even if multiple are present; C<< $c->req->param( 'foo' ) >> will
522 return a list of as many are present, which can have unexpected consequences
523 when writing code of the form:
527 baz => $c->req->param( 'baz' ),
530 If multiple C<baz> parameters are provided this code might corrupt data or
531 cause a hash initialization error. For a more straightforward interface see
532 C<< $c->req->parameters >>.
540 return keys %{ $self->parameters };
547 unless ( exists $self->parameters->{$param} ) {
548 return wantarray ? () : undef;
551 if ( ref $self->parameters->{$param} eq 'ARRAY' ) {
553 ? @{ $self->parameters->{$param} }
554 : $self->parameters->{$param}->[0];
558 ? ( $self->parameters->{$param} )
559 : $self->parameters->{$param};
564 $self->parameters->{$field} = [@_];
568 =head2 $req->parameters
570 Returns a reference to a hash containing GET and POST parameters. Values can
571 be either a scalar or an arrayref containing scalars.
573 print $c->request->parameters->{field};
574 print $c->request->parameters->{field}->[0];
576 This is the combination of C<query_parameters> and C<body_parameters>.
580 Shortcut for $req->parameters.
584 Returns the path, i.e. the part of the URI after $req->base, for the current request.
586 http://localhost/path/foo
588 $c->request->path will contain 'path/foo'
590 =head2 $req->path_info
592 Alias for path, added for compatibility with L<CGI>.
597 my ( $self, @params ) = @_;
600 $self->uri->path(@params);
603 elsif ( $self->_has_path ) {
607 my $path = $self->uri->path;
608 my $location = $self->base->path;
609 $path =~ s/^(\Q$location\E)?//;
617 =head2 $req->protocol
619 Returns the protocol (HTTP/1.0 or HTTP/1.1) used for the current request.
621 =head2 $req->query_parameters
623 =head2 $req->query_params
625 Returns a reference to a hash containing query string (GET) parameters. Values can
626 be either a scalar or an arrayref containing scalars.
628 print $c->request->query_parameters->{field};
629 print $c->request->query_parameters->{field}->[0];
631 =head2 $req->read( [$maxlength] )
633 Reads a chunk of data from the request body. This method is intended to be
634 used in a while loop, reading $maxlength bytes on every call. $maxlength
635 defaults to the size of the request if not specified.
637 =head2 $req->read_chunk(\$buff, $max)
641 You have to set MyApp->config(parse_on_demand => 1) to use this directly.
645 Shortcut for $req->headers->referer. Returns the referring page.
649 Returns true or false, indicating whether the connection is secure
650 (https). Note that the URI scheme (e.g., http vs. https) must be determined
651 through heuristics, and therefore the reliability of $req->secure will depend
652 on your server configuration. If you are serving secure pages on the standard
653 SSL port (443) and/or setting the HTTPS environment variable, $req->secure
656 =head2 $req->captures
658 Returns a reference to an array containing captured args from chained
659 actions or regex captures.
661 my @captures = @{ $c->request->captures };
665 A convenient method to access $req->uploads.
667 $upload = $c->request->upload('field');
668 @uploads = $c->request->upload('field');
669 @fields = $c->request->upload;
671 for my $upload ( $c->request->upload('field') ) {
672 print $upload->filename;
681 return keys %{ $self->uploads };
688 unless ( exists $self->uploads->{$upload} ) {
689 return wantarray ? () : undef;
692 if ( ref $self->uploads->{$upload} eq 'ARRAY' ) {
694 ? @{ $self->uploads->{$upload} }
695 : $self->uploads->{$upload}->[0];
699 ? ( $self->uploads->{$upload} )
700 : $self->uploads->{$upload};
706 while ( my ( $field, $upload ) = splice( @_, 0, 2 ) ) {
708 if ( exists $self->uploads->{$field} ) {
709 for ( $self->uploads->{$field} ) {
710 $_ = [$_] unless ref($_) eq "ARRAY";
711 push( @$_, $upload );
715 $self->uploads->{$field} = $upload;
723 Returns a reference to a hash containing uploads. Values can be either a
724 L<Catalyst::Request::Upload> object, or an arrayref of
725 L<Catalyst::Request::Upload> objects.
727 my $upload = $c->request->uploads->{field};
728 my $upload = $c->request->uploads->{field}->[0];
732 Returns a L<URI> object for the current request. Stringifies to the URI text.
734 =head2 $req->mangle_params( { key => 'value' }, $appendmode);
736 Returns a hashref of parameters stemming from the current request's params,
737 plus the ones supplied. Keys for which no current param exists will be
738 added, keys with undefined values will be removed and keys with existing
739 params will be replaced. Note that you can supply a true value as the final
740 argument to change behavior with regards to existing parameters, appending
741 values rather than replacing them.
745 # URI query params foo=1
746 my $hashref = $req->mangle_params({ foo => 2 });
747 # Result is query params of foo=2
751 # URI query params foo=1
752 my $hashref = $req->mangle_params({ foo => 2 }, 1);
753 # Result is query params of foo=1&foo=2
755 This is the code behind C<uri_with>.
760 my ($self, $args, $append) = @_;
762 carp('No arguments passed to mangle_params()') unless $args;
764 foreach my $value ( values %$args ) {
765 next unless defined $value;
766 for ( ref $value eq 'ARRAY' ? @$value : $value ) {
768 utf8::encode( $_ ) if utf8::is_utf8($_);
772 my %params = %{ $self->uri->query_form_hash };
773 foreach my $key (keys %{ $args }) {
774 my $val = $args->{$key};
777 if($append && exists($params{$key})) {
779 # This little bit of heaven handles appending a new value onto
780 # an existing one regardless if the existing value is an array
781 # or not, and regardless if the new value is an array or not
783 ref($params{$key}) eq 'ARRAY' ? @{ $params{$key} } : $params{$key},
784 ref($val) eq 'ARRAY' ? @{ $val } : $val
788 $params{$key} = $val;
792 # If the param wasn't defined then we delete it.
793 delete($params{$key});
801 =head2 $req->uri_with( { key => 'value' } );
803 Returns a rewritten URI object for the current request. Key/value pairs
804 passed in will override existing parameters. You can remove an existing
805 parameter by passing in an undef value. Unmodified pairs will be
808 You may also pass an optional second parameter that puts C<uri_with> into
811 $req->uri_with( { key => 'value' }, { mode => 'append' } );
813 See C<mangle_params> for an explanation of this behavior.
818 my( $self, $args, $behavior) = @_;
820 carp( 'No arguments passed to uri_with()' ) unless $args;
823 if((ref($behavior) eq 'HASH') && defined($behavior->{mode}) && ($behavior->{mode} eq 'append')) {
827 my $params = $self->mangle_params($args, $append);
829 my $uri = $self->uri->clone;
830 $uri->query_form($params);
835 =head2 $req->remote_user
837 Returns the value of the C<REMOTE_USER> environment variable.
839 =head2 $req->user_agent
841 Shortcut to $req->headers->user_agent. Returns the user agent (browser)
846 You should never need to call these yourself in application code,
847 however they are useful if extending Catalyst by applying a request role.
849 =head2 $self->prepare_headers()
851 Sets up the C<< $res->headers >> accessor.
853 =head2 $self->prepare_body()
855 Sets up the body using L<HTTP::Body>
857 =head2 $self->prepare_body_chunk()
859 Add a chunk to the request body.
861 =head2 $self->prepare_body_parameters()
863 Sets up parameters from body.
865 =head2 $self->prepare_cookies()
867 Parse cookies from header. Sets up a L<CGI::Simple::Cookie> object.
869 =head2 $self->prepare_connection()
871 Sets up various fields in the request like the local and remote addresses,
872 request method, vhost requested etc.
874 =head2 $self->prepare_parameters()
876 Ensures that the body has been parsed, then builds the parameters, which are
877 combined from those in the request and those in the body.
879 This method is the builder for the 'parameters' attribute.
887 Catalyst Contributors, see Catalyst.pm
891 This library is free software. You can redistribute it and/or modify
892 it under the same terms as Perl itself.
896 __PACKAGE__->meta->make_immutable;