Rewrite REST _METHOD action handling to fake being a real action, and ergo appear... fixes_5_80_forward_stats_warnings
t0m [Mon, 29 Jun 2009 22:45:33 +0000 (23:45 +0100)]
lib/Catalyst/Action/REST.pm

index 26c4933..d887f22 100644 (file)
@@ -91,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;