Rewrite REST _METHOD action handling to fake being a real action, and ergo appear...
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / REST.pm
index 06f1d6c..d887f22 100644 (file)
@@ -18,13 +18,14 @@ use Catalyst::Controller::REST;
 
 BEGIN { require 5.008001; }
 
-our $VERSION = '0.67';
+our $VERSION = '0.73';
 
-# This is wrong in several ways. First, there's no guarantee that
-# Catalyst.pm has not been subclassed. Two, there's no guarantee that
-# the user isn't already using their request subclass.
-Catalyst->request_class('Catalyst::Request::REST')
-  unless Catalyst->request_class->isa('Catalyst::Request::REST');
+sub new {
+  my $class  = shift;
+  my $config = shift;
+  Catalyst::Request::REST->_insert_self_into( $config->{class} );
+  return $class->SUPER::new($config, @_);
+}
 
 =head1 NAME
 
@@ -90,58 +91,60 @@ sub dispatch {
 
     my $controller = $c->component( $self->class );
     my $method     = $self->name . "_" . uc( $c->request->method );
-    if ( $controller->can($method) ) {
-        $c->execute( $self->class, $self, @{ $c->req->args } );
-        return $controller->$method( $c, @{ $c->req->args } );
-    } else {
-        if ( $c->request->method eq "OPTIONS" ) {
-            return $self->_return_options($c);
-        } else {
-            my $handle_ni = $self->name . "_not_implemented";
-            if ( $controller->can($handle_ni) ) {
-                return $controller->$handle_ni( $c, @{ $c->req->args } );
-            } else {
-                return $self->_return_not_implemented($c);
-            }
-        }
+
+    if (my $code = $controller->can($method)) {
+        $c->execute( $self->class, $self, @{ $c->req->args } ) if $code;
+        local $self->{reverse} = $self->{reverse} . "_" . uc( $c->request->method );
+        local $self->{code} = $code;
+
+        return $c->execute( $self->class, $self, @{ $c->req->args } );
     }
-}
+    if ($c->request->method eq "OPTIONS") {
+        local $self->{reverse} = $self->{reverse} . "_" . uc( $c->request->method );
+        local $self->{code} = sub { $self->can('_return_options')->($self->name, @_) };
+        return $c->execute( $self->class, $self, @{ $c->req->args } );
+    }
+    my $not_implemented_method = $self->name . "_not_implemented";
+    local $self->{code} = $controller->can($not_implemented_method)
+        || sub { $self->can('_return_not_implemented')->($self->name, @_); };
 
-sub _return_options {
-    my ( $self, $c ) = @_;
+    local $self->{reverse} = $not_implemented_method;
 
-    my @allowed = $self->_get_allowed_methods($c);
-    $c->response->content_type('text/plain');
-    $c->response->status(200);
-    $c->response->header( 'Allow' => \@allowed );
+    $c->execute( $self->class, $self, @{ $c->req->args } );
 }
 
-sub _get_allowed_methods {
-    my ( $self, $c ) = @_;
-
-    my $controller = $self->class;
-    my $methods    = Class::Inspector->methods($controller);
+my $_get_allowed_methods = sub {
+    my ( $controller, $c, $name ) = @_;
+    my $class = ref($controller) ? ref($controller) : $controller;
+    my $methods    = Class::Inspector->methods($class);
     my @allowed;
     foreach my $method ( @{$methods} ) {
-        my $name = $self->name;
         if ( $method =~ /^$name\_(.+)$/ ) {
             push( @allowed, $1 );
         }
     }
     return @allowed;
+};
+
+sub _return_options {
+    my ( $method_name, $controller, $c) = @_;
+    my @allowed = $controller->$_get_allowed_methods($c, $method_name);
+    $c->response->content_type('text/plain');
+    $c->response->status(200);
+    $c->response->header( 'Allow' => \@allowed );
 }
 
 sub _return_not_implemented {
-    my ( $self, $c ) = @_;
+    my ( $method_name, $controller, $c ) = @_;
 
-    my @allowed = $self->_get_allowed_methods($c);
+    my @allowed = $controller->$_get_allowed_methods($c, $method_name);
     $c->response->content_type('text/plain');
     $c->response->status(405);
     $c->response->header( 'Allow' => \@allowed );
     $c->response->body( "Method "
           . $c->request->method
           . " not implemented for "
-          . $c->uri_for( $self->reverse ) );
+          . $c->uri_for( $method_name ) );
 }
 
 1;
@@ -163,7 +166,10 @@ L<Catalyst::Action::Serialize>, L<Catalyst::Action::Deserialize>
 
 A:  Most likely, you haven't set Content-type equal to "application/json", or one of the 
 accepted return formats.  You can do this by setting it in your query string thusly:
-?content-type=application%2Fjson (where %2F == / uri escaped). **NOTE** Apache will refuse %2F unless configured otherise.
+?content-type=application%2Fjson (where %2F == / uri escaped). 
+
+**NOTE** Apache will refuse %2F unless configured otherise.
+Make sure AllowEncodedSlashes On is in your httpd.conf file in order for this to run smoothly.
 
 =cut