X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FAction%2FSerialize.pm;h=73855b3f63a510a0f2a818fde812ae9a31512552;hb=d0822465cc09629df95ad9c522bce758f2badc8c;hp=a55d5317a6c6b4845eb021f55eb8407e911245d1;hpb=367b3ff4e4444df4d20e8688c1cad9e1f59a3ba5;p=catagits%2FCatalyst-Action-REST.git diff --git a/lib/Catalyst/Action/Serialize.pm b/lib/Catalyst/Action/Serialize.pm index a55d531..73855b3 100644 --- a/lib/Catalyst/Action/Serialize.pm +++ b/lib/Catalyst/Action/Serialize.pm @@ -1,59 +1,69 @@ -# -# Catlyst::Action::Serialize.pm -# Created by: Adam Jacob, Marchex, -# -# $Id$ - package Catalyst::Action::Serialize; -use strict; -use warnings; +use Moose; +use namespace::autoclean; -use base 'Catalyst::Action::SerializeBase'; +extends 'Catalyst::Action::SerializeBase'; use Module::Pluggable::Object; -use Data::Dump qw(dump); +use MRO::Compat; + +our $VERSION = '1.02'; +$VERSION = eval $VERSION; + +has _encoders => ( + is => 'ro', + isa => 'HashRef', + default => sub { {} }, +); sub execute { my $self = shift; my ( $controller, $c ) = @_; - $self->NEXT::execute(@_); + $self->maybe::next::method(@_); return 1 if $c->req->method eq 'HEAD'; - return 1 if length( $c->response->body ); + return 1 if $c->response->has_body; return 1 if scalar @{ $c->error }; - return 1 if $c->response->status =~ /^(?:204|3\d\d)$/; + return 1 if $c->response->status =~ /^(?:204)$/; my ( $sclass, $sarg, $content_type ) = $self->_load_content_plugins( "Catalyst::Action::Serialize", $controller, $c ); unless ( defined($sclass) ) { if ( defined($content_type) ) { - $c->log->debug("Could not find a serializer for $content_type"); + $c->log->info("Could not find a serializer for $content_type"); } else { - $c->log->debug( - "Could not find a serializer for an empty content type"); + $c->log->info( + "Could not find a serializer for an empty content-type"); } return 1; } $c->log->debug( - "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) ); + "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) ) if $c->debug; + + $self->_encoders->{$sclass} ||= $sclass->new; + my $sobj = $self->_encoders->{$sclass}; my $rc; - if ( defined($sarg) ) { - $rc = $sclass->execute( $controller, $c, $sarg ); - } else { - $rc = $sclass->execute( $controller, $c ); - } - if ( $rc eq 0 ) { - return $self->_unsupported_media_type( $c, $content_type ); - } elsif ( $rc ne 1 ) { - return $self->_serialize_bad_request( $c, $content_type, $rc ); + eval { + if ( defined($sarg) ) { + $rc = $sobj->execute( $controller, $c, $sarg ); + } else { + $rc = $sobj->execute( $controller, $c ); + } + }; + if ($@) { + return $self->serialize_bad_request( $c, $content_type, $@ ); + } elsif (!$rc) { + return $self->unsupported_media_type( $c, $content_type ); } return 1; } +__PACKAGE__->meta->make_immutable; + 1; =head1 NAME @@ -65,14 +75,12 @@ Catalyst::Action::Serialize - Serialize Data in a Response package Foo::Controller::Bar; __PACKAGE__->config( - serialize => { - 'default' => 'text/x-yaml', - 'stash_key' => 'rest', - 'map' => { - 'text/html' => [ 'View', 'TT', ], - 'text/x-yaml' => 'YAML', - 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], - }, + 'default' => 'text/x-yaml', + 'stash_key' => 'rest', + 'map' => { + 'text/html' => [ 'View', 'TT', ], + 'text/x-yaml' => 'YAML', + 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], } ); @@ -83,12 +91,11 @@ Catalyst::Action::Serialize - Serialize Data in a Response This action will serialize the body of an HTTP Response. The serializer is selected by introspecting the HTTP Requests content-type header. -It requires that your Catalyst controller have a "serialize" entry -in it's configuration, which sets up the mapping between Content Type's -and Serialization classes. +It requires that your Catalyst controller is properly configured to set up the +mapping between Content Type's and Serialization classes. -The specifics of serializing each content-type is implemented as -a plugin to L. +The specifics of serializing each content-type is implemented as a plugin to +L. Typically, you would use this ActionClass on your C method. However, nothing is stopping you from choosing specific methods to Serialize: @@ -102,33 +109,43 @@ L. =head1 CONFIGURATION -=over 4 +=head2 map -=item default +Takes a hashref, mapping Content-Types to a given serializer plugin. -The Content-Type of the default Serialization format. This must be a -Content-Type associated with a plugin in the "map" section below. +=head2 default -This is used if a requested content-type is not recognized. +This is the 'fall-back' Content-Type if none of the requested or acceptable +types is found in the L. It must be an entry in the L. -=item stash_key +=head2 stash_key -We will serialize the data that lives in this location in the stash. So -if the value is "rest", we will serialize the data under: +Specifies the key of the stash entry holding the data that is to be serialized. +So if the value is "rest", we will serialize the data under: $c->stash->{'rest'} -=item map +=head2 content_type_stash_key -Takes a hashref, mapping Content-Types to a given plugin. +Specifies the key of the stash entry that optionally holds an overriding +Content-Type. If set, and if the specified stash entry has a valid value, +then it takes priority over the requested content types. -=back +This can be useful if you want to dynamically force a particular content type, +perhaps for debugging. =head1 HELPFUL PEOPLE Daisuke Maki pointed out that early versions of this Action did not play well with others, or generally behave in a way that was very consistent -with the rest of Catalyst. +with the rest of Catalyst. + +=head1 CUSTOM ERRORS + +For building custom error responses when serialization fails, you can create +an ActionRole (and use L to apply it to the +C action) which overrides C and/or C<_serialize_bad_request> +methods. =head1 SEE ALSO @@ -137,15 +154,12 @@ a sensible set of defaults for doing a REST controller. L, L -=head1 AUTHOR - -Adam Jacob , with lots of help from mst and jrockway +=head1 AUTHORS -Marchex, Inc. paid me while I developed this module. (http://www.marchex.com) +See L for authors. =head1 LICENSE You may distribute this code under the same terms as Perl itself. =cut -