Skip to content

Commit

Permalink
Rewrite REST _METHOD action handling to fake being a real action, and…
Browse files Browse the repository at this point in the history
… ergo appear in the stats table as you would expect. I like what this does, but my implementation here is hideous..
  • Loading branch information
bobtfish committed Jun 29, 2009
1 parent 765170f commit 679978b
Showing 1 changed file with 32 additions and 30 deletions.
62 changes: 32 additions & 30 deletions lib/Catalyst/Action/REST.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 679978b

Please sign in to comment.