Version 1.06
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / Serialize.pm
CommitLineData
7ad87df9 1package Catalyst::Action::Serialize;
2
930013e6 3use Moose;
4use namespace::autoclean;
7ad87df9 5
930013e6 6extends 'Catalyst::Action::SerializeBase';
7ad87df9 7use Module::Pluggable::Object;
def65dcc 8use MRO::Compat;
7ad87df9 9
05b98ffc 10our $VERSION = '1.06';
f465980c 11$VERSION = eval $VERSION;
12
0c14c8cd 13has _encoders => (
14 is => 'ro',
15 isa => 'HashRef',
16 default => sub { {} },
17);
18
7ad87df9 19sub execute {
20 my $self = shift;
21 my ( $controller, $c ) = @_;
22
def65dcc 23 $self->maybe::next::method(@_);
e601adda 24
7ad87df9 25 return 1 if $c->req->method eq 'HEAD';
786c212f 26 return 1 if $c->response->has_body;
7ad87df9 27 return 1 if scalar @{ $c->error };
bdff70a9 28 return 1 if $c->response->status =~ /^(?:204)$/;
7ad87df9 29
9a76221e 30 my ( $sclass, $sarg, $content_type ) =
31 $self->_load_content_plugins( "Catalyst::Action::Serialize",
32 $controller, $c );
51cc8fe9 33 unless ( defined($sclass) ) {
9a76221e 34 if ( defined($content_type) ) {
faf5c20b 35 $c->log->info("Could not find a serializer for $content_type");
9a76221e 36 } else {
faf5c20b 37 $c->log->info(
9cd203c9 38 "Could not find a serializer for an empty content-type");
9a76221e 39 }
51cc8fe9 40 return 1;
41 }
9a76221e 42 $c->log->debug(
faf5c20b 43 "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) ) if $c->debug;
7ad87df9 44
0c14c8cd 45 $self->_encoders->{$sclass} ||= $sclass->new;
46 my $sobj = $self->_encoders->{$sclass};
47
e601adda 48 my $rc;
878b2b54 49 eval {
50 if ( defined($sarg) ) {
0c14c8cd 51 $rc = $sobj->execute( $controller, $c, $sarg );
878b2b54 52 } else {
0c14c8cd 53 $rc = $sobj->execute( $controller, $c );
878b2b54 54 }
55 };
56 if ($@) {
b3996af8 57 return $self->serialize_bad_request( $c, $content_type, $@ );
878b2b54 58 } elsif (!$rc) {
b3996af8 59 return $self->unsupported_media_type( $c, $content_type );
9a76221e 60 }
7ad87df9 61
62 return 1;
eccb2137 63}
7ad87df9 64
05009b91 65__PACKAGE__->meta->make_immutable;
398c5a1b 66
d2c41c14 671;
68
398c5a1b 69=head1 NAME
70
71Catalyst::Action::Serialize - Serialize Data in a Response
72
73=head1 SYNOPSIS
74
75 package Foo::Controller::Bar;
76
77 __PACKAGE__->config(
faf5c20b 78 'default' => 'text/x-yaml',
79 'stash_key' => 'rest',
80 'map' => {
81 'text/html' => [ 'View', 'TT', ],
82 'text/x-yaml' => 'YAML',
83 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
398c5a1b 84 }
85 );
86
e601adda 87 sub end :ActionClass('Serialize') {}
398c5a1b 88
89=head1 DESCRIPTION
90
91This action will serialize the body of an HTTP Response. The serializer is
e601adda 92selected by introspecting the HTTP Requests content-type header.
398c5a1b 93
faf5c20b 94It requires that your Catalyst controller is properly configured to set up the
95mapping between Content Type's and Serialization classes.
398c5a1b 96
faf5c20b 97The specifics of serializing each content-type is implemented as a plugin to
98L<Catalyst::Action::Serialize>.
398c5a1b 99
e601adda 100Typically, you would use this ActionClass on your C<end> method. However,
101nothing is stopping you from choosing specific methods to Serialize:
102
103 sub foo :Local :ActionClass('Serialize') {
104 .. populate stash with data ..
105 }
106
9a76221e 107When you use this module, the request class will be changed to
108L<Catalyst::Request::REST>.
109
398c5a1b 110=head1 CONFIGURATION
111
a51e7bbd 112=head2 map
398c5a1b 113
a51e7bbd 114Takes a hashref, mapping Content-Types to a given serializer plugin.
398c5a1b 115
a51e7bbd 116=head2 default
367b3ff4 117
a51e7bbd 118This is the 'fall-back' Content-Type if none of the requested or acceptable
119types is found in the L</map>. It must be an entry in the L</map>.
398c5a1b 120
0c14c8cd 121=head2 stash_key
398c5a1b 122
a51e7bbd 123Specifies the key of the stash entry holding the data that is to be serialized.
124So if the value is "rest", we will serialize the data under:
e601adda 125
126 $c->stash->{'rest'}
398c5a1b 127
a51e7bbd 128=head2 content_type_stash_key
398c5a1b 129
a51e7bbd 130Specifies the key of the stash entry that optionally holds an overriding
131Content-Type. If set, and if the specified stash entry has a valid value,
132then it takes priority over the requested content types.
398c5a1b 133
a51e7bbd 134This can be useful if you want to dynamically force a particular content type,
135perhaps for debugging.
398c5a1b 136
e601adda 137=head1 HELPFUL PEOPLE
138
139Daisuke Maki pointed out that early versions of this Action did not play
140well with others, or generally behave in a way that was very consistent
0c14c8cd 141with the rest of Catalyst.
e601adda 142
b3996af8 143=head1 CUSTOM ERRORS
144
145For building custom error responses when serialization fails, you can create
146an ActionRole (and use L<Catalyst::Controller::ActionRole> to apply it to the
147C<end> action) which overrides C<unsupported_media_type> and/or C<_serialize_bad_request>
148methods.
149
398c5a1b 150=head1 SEE ALSO
151
152You likely want to look at L<Catalyst::Controller::REST>, which implements
e601adda 153a sensible set of defaults for doing a REST controller.
398c5a1b 154
155L<Catalyst::Action::Deserialize>, L<Catalyst::Action::REST>
156
5cb5f6bb 157=head1 AUTHORS
398c5a1b 158
5cb5f6bb 159See L<Catalyst::Action::REST> for authors.
398c5a1b 160
161=head1 LICENSE
162
163You may distribute this code under the same terms as Perl itself.
164
165=cut