Add deserialize_http_methods attribute to Catalyst::Action::Deserialize.
Johannes Plunien [Sun, 31 Jul 2011 16:17:53 +0000 (20:17 +0400)]
lib/Catalyst/Action/Deserialize.pm
t/catalyst-action-deserialize.t
t/lib/Test/Catalyst/Action/REST/Controller/Deserialize.pm

index 4fbbde6..b87e236 100644 (file)
@@ -12,13 +12,23 @@ $VERSION = eval $VERSION;
 
 has plugins => ( is => 'rw' );
 
+has deserialize_http_methods => (
+    traits  => ['Array'],
+    isa     => 'ArrayRef[Str]',
+    builder => '_build_deserialize_http_methods',
+    handles => {
+        deserialize_http_methods => 'elements',
+    },
+);
+
+sub _build_deserialize_http_methods { [qw(POST PUT OPTIONS DELETE)] }
+
 sub execute {
     my $self = shift;
     my ( $controller, $c ) = @_;
 
-    my @demethods = qw(POST PUT OPTIONS DELETE);
     my $method    = $c->request->method;
-    if ( grep /^$method$/, @demethods ) {
+    if ( grep /^$method$/, $self->deserialize_http_methods ) {
         my ( $sclass, $sarg, $content_type ) =
           $self->_load_content_plugins( 'Catalyst::Action::Deserialize',
             $controller, $c );
@@ -64,11 +74,27 @@ Catalyst::Action::Deserialize - Deserialize Data in a Request
 
 =head1 DESCRIPTION
 
-This action will deserialize HTTP POST, PUT, and OPTIONS requests.
+This action will deserialize HTTP POST, PUT, OPTIONS and DELETE requests.
 It assumes that the body of the HTTP Request is a serialized object.
 The serializer is selected by introspecting the requests content-type
 header.
 
+If you want deserialize any other HTTP method besides POST, PUT,
+OPTIONS and DELETE you can do this by setting the
+C<< deserialize_http_methods >> list via C<< action_args >>.
+Just modify the config in your controller and define a list of HTTP
+methods the deserialization should happen for:
+
+    __PACKAGE__->config(
+        action_args => {
+            '*' => {
+                deserialize_http_methods => [qw(POST PUT OPTIONS DELETE GET)]
+            }
+        }
+    );
+
+See also L<Catalyst::Controller/action_args>.
+
 The specifics of deserializing each content-type is implemented as
 a plugin to L<Catalyst::Action::Deserialize>.  You can see a list
 of currently implemented plugins in L<Catalyst::Controller::REST>.
index 52ec2b2..6c37717 100644 (file)
@@ -13,10 +13,17 @@ my $t = Test::Rest->new('content_type' => 'text/x-yaml');
 use_ok 'Catalyst::Test', 'Test::Catalyst::Action::REST';
 my $url = '/deserialize/test';
 
-my $res = request($t->put( url => $url, data => Dump({ kitty => "LouLou" })));
+my $req = $t->put( url => $url, data => Dump({ kitty => "LouLou" }));
+my $res = request($req);
 ok( $res->is_success, 'PUT Deserialize request succeeded' );
 is( $res->content, "LouLou", "Request returned deserialized data");
 
+$req->method('GET');
+isnt( request($req)->content, 'LouLou', 'GET request with body does not work by default' );
+
+$req->url('/deserialize/test_action_args');
+is( request($req)->content, 'LouLou', 'GET request via action_args');
+
 my $nt = Test::Rest->new('content_type' => 'text/broken');
 my $bres = request($nt->put( url => $url, data => Dump({ kitty => "LouLou" })));
 is( $bres->code, 415, 'PUT on un-useable Deserialize class returns 415');
index 832b51a..d7723e2 100644 (file)
@@ -5,6 +5,11 @@ use namespace::autoclean;
 BEGIN { extends 'Catalyst::Controller' }
 
 __PACKAGE__->config(
+    'action_args' => {
+        'test_action_args' => {
+            'deserialize_http_methods' => [qw(POST PUT OPTIONS DELETE GET)]
+        }
+    },
     'stash_key' => 'rest',
     'map'       => {
         'text/x-yaml'        => 'YAML',
@@ -19,4 +24,9 @@ sub test :Local :ActionClass('Deserialize') {
     $c->res->output($c->req->data->{'kitty'});
 }
 
+sub test_action_args :Local :ActionClass('Deserialize') {
+    my ( $self, $c ) = @_;
+    $c->res->output($c->req->data->{'kitty'});
+}
+
 1;