X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FAction%2FSerialize.pm;h=549e312a83d3e2023599d105841cc26752e6175c;hb=faf5c20bff09c91f18b46a3d3d8349379aa36192;hp=d747576987e3626b4948183bb9979231dcf99cd0;hpb=7ad87df957f65463dba321ebe616e2581b7ff58f;p=catagits%2FCatalyst-Action-REST.git diff --git a/lib/Catalyst/Action/Serialize.pm b/lib/Catalyst/Action/Serialize.pm index d747576..549e312 100644 --- a/lib/Catalyst/Action/Serialize.pm +++ b/lib/Catalyst/Action/Serialize.pm @@ -9,69 +9,140 @@ package Catalyst::Action::Serialize; use strict; use warnings; -use base 'Catalyst::Action'; +use base 'Catalyst::Action::SerializeBase'; use Module::Pluggable::Object; - -__PACKAGE__->mk_accessors(qw(plugins)); +use Data::Dump qw(dump); sub execute { my $self = shift; my ( $controller, $c ) = @_; + $self->NEXT::execute(@_); + return 1 if $c->req->method eq 'HEAD'; return 1 if length( $c->response->body ); return 1 if scalar @{ $c->error }; return 1 if $c->response->status =~ /^(?:204|3\d\d)$/; - # Load the Serialize Classes - unless(defined($self->plugins)) { - my $mpo = Module::Pluggable::Object->new( - 'require' => 1, - 'search_path' => [ 'Catalyst::Action::Serialize' ], - ); - my @plugins = $mpo->plugins; - $self->plugins(\@plugins); - } - - # Look up what serializer to use from content_type map - # - # If we don't find one, we use the default - my $content_type = $c->request->content_type; - my $sclass = 'Catalyst::Action::Serialize::'; - my $sarg; - my $map = $controller->serialize->{'map'}; - if (exists($map->{$content_type})) { - my $mc; - if (ref($map->{$content_type}) eq "ARRAY") { - $mc = $map->{$content_type}->[0]; - $sarg = $map->{$content_type}->[1]; - } else { - $mc = $map->{$content_type}; - } - $sclass .= $mc; - if (! grep(/^$sclass$/, @{$self->plugins})) { - die "Cannot find plugin $sclass for $content_type!"; - } - } else { - if (exists($controller->serialize->{'default'})) { - $sclass .= $controller->serialize->{'default'}; + my ( $sclass, $sarg, $content_type ) = + $self->_load_content_plugins( "Catalyst::Action::Serialize", + $controller, $c ); + unless ( defined($sclass) ) { + if ( defined($content_type) ) { + $c->log->info("Could not find a serializer for $content_type"); } else { - die "I cannot find a default serializer!"; + $c->log->info( + "Could not find a serializer for an empty content type"); } + return 1; } + $c->log->debug( + "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) ) if $c->debug; - # Go ahead and serialize ourselves - if (defined($sarg)) { - $sclass->execute($controller, $c, $sarg); + my $rc; + if ( defined($sarg) ) { + $rc = $sclass->execute( $controller, $c, $sarg ); } else { - $sclass->execute($controller, $c); + $rc = $sclass->execute( $controller, $c ); } - - if (! $c->response->content_type ) { - $c->response->content_type($c->request->content_type); + 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 ); } return 1; -}; +} 1; + +=head1 NAME + +Catalyst::Action::Serialize - Serialize Data in a Response + +=head1 SYNOPSIS + + package Foo::Controller::Bar; + + __PACKAGE__->config( + 'default' => 'text/x-yaml', + 'stash_key' => 'rest', + 'map' => { + 'text/html' => [ 'View', 'TT', ], + 'text/x-yaml' => 'YAML', + 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], + } + ); + + sub end :ActionClass('Serialize') {} + +=head1 DESCRIPTION + +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 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. + +Typically, you would use this ActionClass on your C method. However, +nothing is stopping you from choosing specific methods to Serialize: + + sub foo :Local :ActionClass('Serialize') { + .. populate stash with data .. + } + +When you use this module, the request class will be changed to +L. + +=head1 CONFIGURATION + +=over 4 + +=item default + +The Content-Type of the default Serialization format. This must be a +Content-Type associated with a plugin in the "map" section below. + +This is used if a requested content-type is not recognized. + +=item 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: + + $c->stash->{'rest'} + +=item map + +Takes a hashref, mapping Content-Types to a given plugin. + +=back + +=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. + +=head1 SEE ALSO + +You likely want to look at L, which implements +a sensible set of defaults for doing a REST controller. + +L, L + +=head1 AUTHOR + +Adam Jacob , with lots of help from mst and jrockway + +Marchex, Inc. paid me while I developed this module. (http://www.marchex.com) + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. + +=cut +