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