Merge branch 'master' into roles-saner
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / SerializeBase.pm
index b7a6765..399899d 100644 (file)
@@ -10,12 +10,12 @@ use strict;
 use warnings;
 
 use base 'Catalyst::Action';
+use Moose::Util qw(does_role);
+use Catalyst::ControllerRole::SerializeConfig;
 use Module::Pluggable::Object;
-use Data::Dump qw(dump);
-use Catalyst::Request::REST;
-
-Catalyst->request_class('Catalyst::Request::REST')
-    unless Catalyst->request_class->isa('Catalyst::Request::REST');
+use Catalyst::RequestRole::REST;
+use Catalyst::ResponseRole::REST;
+use Catalyst::Utils ();
 
 __PACKAGE__->mk_accessors(qw(_serialize_plugins _loaded_plugins));
 
@@ -23,6 +23,12 @@ sub _load_content_plugins {
     my $self = shift;
     my ( $search_path, $controller, $c ) = @_;
 
+    Catalyst::RequestRole::REST->meta->apply($c->request)
+      unless does_role($c->request, 'Catalyst::RequestRole::REST');
+
+    Catalyst::ResponseRole::REST->meta->apply($c->response)
+      unless does_role($c->response, 'Catalyst::ResponseRole::REST');
+
     unless ( defined( $self->_loaded_plugins ) ) {
         $self->_loaded_plugins( {} );
     }
@@ -43,27 +49,34 @@ sub _load_content_plugins {
     my $sarg;
     my $map;
 
-    my $config;
+    Catalyst::ControllerRole::SerializeConfig->meta->apply($controller)
+      unless does_role($controller, 'Catalyst::ControllerRole::SerializeConfig');
+
+    my $config = $controller->serialize_config;
     
-    if ( exists $controller->config->{'serialize'} ) {
-        $c->log->info("Using deprecated configuration for Catalyst::Action::REST!");
-        $c->log->info("Please see perldoc Catalyst::Action::REST for the update guide");
-        $config = $controller->config->{'serialize'};
-    } else {
-        $config = $controller->config;
+    $map = $config->{map};
+
+    # pick preferred content type
+    my @accepted_types; # priority order, best first
+    # give top priority to content type specified by stash, if any
+    my $content_type_stash_key = $config->{content_type_stash_key};
+    if ($content_type_stash_key
+        and my $stashed = $c->stash->{$content_type_stash_key}
+    ) {
+        # convert to array if not already a ref
+        $stashed = [ $stashed ] if not ref $stashed;
+        push @accepted_types, @$stashed;
     }
-    $map = $config->{'map'};
-    # If we don't have a handler for our preferred content type, try
-    # the default
-
-    my ($content_type) = grep { $map->{$_} } @{$c->request->accepted_content_types};
-
-    unless ( defined $content_type ) {
-        if( exists $config->{'default'} ) {
-            $content_type = $config->{'default'} ;
-        } else {
-            return $self->_unsupported_media_type($c, $content_type);
-        }
+    # then content types requested by caller
+    push @accepted_types, @{ $c->request->accepted_content_types };
+    # then the default
+    push @accepted_types, $config->{'default'} if $config->{'default'};
+    # pick the best match that we have a serializer mapping for
+    my ($content_type) = grep { $map->{$_} } @accepted_types;
+
+    unless ($content_type) {
+        $c->response->unsupported_media_type;
+        return;
     }
 
     # carp about old text/x-json
@@ -89,10 +102,12 @@ sub _load_content_plugins {
         $sclass .= $mc;
         #}
         if ( !grep( /^$sclass$/, @{ $self->_serialize_plugins } ) ) {
-            return $self->_unsupported_media_type($c, $content_type);
+            $c->response->unsupported_media_type($content_type);
+            return;
         }
     } else {
-        return $self->_unsupported_media_type($c, $content_type);
+        $c->response->unsupported_media_type($content_type);
+        return;
     }
     unless ( exists( $self->_loaded_plugins->{$sclass} ) ) {
         my $load_class = $sclass;
@@ -102,7 +117,8 @@ sub _load_content_plugins {
         if ($@) {
             $c->log->error(
                 "Error loading $sclass for " . $content_type . ": $!" );
-            return $self->_unsupported_media_type($c, $content_type);
+            $c->response->unsupported_media_type($content_type);
+            return;
         } else {
             $self->_loaded_plugins->{$sclass} = 1;
         }
@@ -120,29 +136,6 @@ sub _load_content_plugins {
     return $sclass, $sarg, $content_type;
 }
 
-sub _unsupported_media_type {
-    my ( $self, $c, $content_type ) = @_;
-    $c->res->content_type('text/plain');
-    $c->res->status(415);
-    if (defined($content_type) && $content_type ne "") {
-        $c->res->body(
-            "Content-Type " . $content_type . " is not supported.\r\n" );
-    } else {
-        $c->res->body(
-            "Cannot find a Content-Type supported by your client.\r\n" );
-    }
-    return undef;
-}
-
-sub _serialize_bad_request {
-    my ( $self, $c, $content_type, $error ) = @_;
-    $c->res->content_type('text/plain');
-    $c->res->status(400);
-    $c->res->body(
-        "Content-Type " . $content_type . " had a problem with your request.\r\n***ERROR***\r\n$error" );
-    return undef;
-}
-
 1;
 
 =head1 NAME