X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FAction%2FREST.pm;h=be267c1a1088886a834dd0c88880e7de4d876435;hb=44fa7f9429568532ea892e2020c20177b71cb736;hp=700e87f65e834a546d8765a1d95cb3b3295c0ea5;hpb=a6b4e496749fd0cf551945716b8d52d990b74ec6;p=catagits%2FCatalyst-Action-REST.git diff --git a/lib/Catalyst/Action/REST.pm b/lib/Catalyst/Action/REST.pm index 700e87f..be267c1 100644 --- a/lib/Catalyst/Action/REST.pm +++ b/lib/Catalyst/Action/REST.pm @@ -10,7 +10,7 @@ use Catalyst::Controller::REST; BEGIN { require 5.008001; } -our $VERSION = '0.90'; +our $VERSION = '1.04'; $VERSION = eval $VERSION; sub BUILDARGS { @@ -61,7 +61,8 @@ by implementing a custom 405 handler like so: If you do not provide an _OPTIONS subroutine, we will automatically respond with a 200 OK. The "Allow" header will be populated with the list of -implemented request methods. +implemented request methods. If you do not provide an _HEAD either, we will +auto dispatch to the _GET one in case it exists. It is likely that you really want to look at L, which brings this class together with automatic Serialization of requests @@ -94,46 +95,61 @@ sub _dispatch_rest_method { my $self = shift; my $c = shift; my $rest_method = shift; + my $req = $c->request; my $controller = $c->component( $self->class ); my ($code, $name); + # Execute normal 'foo' action. + $c->execute( $self->class, $self, @{ $req->args } ); + # Common case, for foo_GET etc if ( $code = $controller->action_for($rest_method) ) { - $c->execute( $self->class, $self, @{ $c->req->args } ); # Execute normal 'foo' action. - return $c->forward( $code, $c->req->args ); # Forward to foo_GET if it's an action + return $c->forward( $code, $req->args ); # Forward to foo_GET if it's an action } elsif ($code = $controller->can($rest_method)) { - # Execute normal action - $c->execute( $self->class, $self, @{ $c->req->args } ); $name = $rest_method; # Stash name and code to run 'foo_GET' like an action below. } - # Generic handling for foo_OPTIONS + # Generic handling for foo_* if (!$code) { - if ( $c->request->method eq "OPTIONS") { - $name = $rest_method; - $code = sub { $self->_return_options($self->name, @_) }; - } - else { - # Otherwise, not implemented. - $name = $self->name . "_not_implemented"; - $code = $controller->can($name) # User method - # Generic not implemented - || sub { $self->_return_not_implemented($self->name, @_) }; - } + my $code_action = { + OPTIONS => sub { + $name = $rest_method; + $code = sub { $self->_return_options($self->name, @_) }; + }, + HEAD => sub { + $rest_method =~ s{_HEAD$}{_GET}i; + $self->_dispatch_rest_method($c, $rest_method); + }, + default => sub { + # Otherwise, not implemented. + $name = $self->name . "_not_implemented"; + $code = $controller->can($name) # User method + # Generic not implemented + || sub { $self->_return_not_implemented($self->name, @_) }; + }, + }; + my ( $http_method, $action_name ) = ( $rest_method, $self->name ); + $http_method =~ s{\Q$action_name\E\_}{}; + my $respond = ($code_action->{$http_method} + || $code_action->{'default'})->(); + return $respond unless $name; } # localise stuff so we can dispatch the action 'as normal, but get # different stats shown, and different code run. + # Also get the full path for the action, and make it look like a forward local $self->{code} = $code; - local $self->{reverse} = $name; + my @name = split m{/}, $self->reverse; + $name[-1] = $name; + local $self->{reverse} = "-> " . join('/', @name); - $c->execute( $self->class, $self, @{ $c->req->args } ); + $c->execute( $self->class, $self, @{ $req->args } ); } -sub _get_allowed_methods { +sub get_allowed_methods { my ( $self, $controller, $c, $name ) = @_; my $class = ref($controller) ? ref($controller) : $controller; my $methods = Class::Inspector->methods($class); @@ -142,16 +158,17 @@ sub _get_allowed_methods { sub _return_options { my ( $self, $method_name, $controller, $c) = @_; - my @allowed = $self->_get_allowed_methods($controller, $c, $method_name); + my @allowed = $self->get_allowed_methods($controller, $c, $method_name); $c->response->content_type('text/plain'); $c->response->status(200); $c->response->header( 'Allow' => \@allowed ); + $c->response->body(q{}); } sub _return_not_implemented { my ( $self, $method_name, $controller, $c ) = @_; - my @allowed = $self->_get_allowed_methods($controller, $c, $method_name); + my @allowed = $self->get_allowed_methods($controller, $c, $method_name); $c->response->content_type('text/plain'); $c->response->status(405); $c->response->header( 'Allow' => \@allowed ); @@ -214,6 +231,8 @@ Daisuke Maki Edaisuke@endeworks.jpE Hans Dieter Pearcey +Brian Phillips Ebphillips@cpan.orgE + Dave Rolsky Eautarch@urth.orgE Luke Saunders @@ -222,9 +241,17 @@ Arthur Axel "fREW" Schmidt Efrioux@gmail.comE J. Shirley Ejshirley@gmail.comE +Gavin Henry Eghenry@surevoip.co.ukE + +Gerv http://www.gerv.net/ + +Colin Newell + +Wallace Reis Ewreis@cpan.orgE + =head1 COPYRIGHT -Copyright (c) 2006-2011 the above named AUTHOR and CONTRIBUTORS +Copyright (c) 2006-2012 the above named AUTHOR and CONTRIBUTORS =head1 LICENSE