Making the default serializer be specified by content-type, not module.
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / Serialize.pm
1 #
2 # Catlyst::Action::Serialize.pm
3 # Created by: Adam Jacob, Marchex, <adam@marchex.com>
4 #
5 # $Id$
6
7 package Catalyst::Action::Serialize;
8
9 use strict;
10 use warnings;
11
12 use base 'Catalyst::Action::SerializeBase';
13 use Module::Pluggable::Object;
14 use Data::Dump qw(dump);
15
16 sub execute {
17     my $self = shift;
18     my ( $controller, $c ) = @_;
19
20     $self->NEXT::execute(@_);
21
22     return 1 if $c->req->method eq 'HEAD';
23     return 1 if length( $c->response->body );
24     return 1 if scalar @{ $c->error };
25     return 1 if $c->response->status =~ /^(?:204|3\d\d)$/;
26
27     my ( $sclass, $sarg, $content_type ) =
28       $self->_load_content_plugins( "Catalyst::Action::Serialize",
29         $controller, $c );
30     unless ( defined($sclass) ) {
31         if ( defined($content_type) ) {
32             $c->log->debug("Could not find a serializer for $content_type");
33         } else {
34             $c->log->debug(
35                 "Could not find a serializer for an empty content type");
36         }
37         return 1;
38     }
39     $c->log->debug(
40         "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) );
41
42     my $rc;
43     if ( defined($sarg) ) {
44         $rc = $sclass->execute( $controller, $c, $sarg );
45     } else {
46         $rc = $sclass->execute( $controller, $c );
47     }
48     if ( $rc eq 0 ) {
49         return $self->_unsupported_media_type( $c, $content_type );
50     } elsif ( $rc ne 1 ) {
51         return $self->_serialize_bad_request( $c, $content_type, $rc );
52     }
53
54     return 1;
55 }
56
57 1;
58
59 =head1 NAME
60
61 Catalyst::Action::Serialize - Serialize Data in a Response
62
63 =head1 SYNOPSIS
64
65     package Foo::Controller::Bar;
66
67     __PACKAGE__->config(
68         serialize => {
69             'default'   => 'text/x-yaml',
70             'stash_key' => 'rest',
71             'map'       => {
72                 'text/html'          => [ 'View', 'TT', ],
73                 'text/x-yaml'        => 'YAML',
74                 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
75             },
76         }
77     );
78
79     sub end :ActionClass('Serialize') {}
80
81 =head1 DESCRIPTION
82
83 This action will serialize the body of an HTTP Response.  The serializer is
84 selected by introspecting the HTTP Requests content-type header.
85
86 It requires that your Catalyst controller have a "serialize" entry
87 in it's configuration, which sets up the mapping between Content Type's
88 and Serialization classes.
89
90 The specifics of serializing each content-type is implemented as
91 a plugin to L<Catalyst::Action::Serialize>.
92
93 Typically, you would use this ActionClass on your C<end> method.  However,
94 nothing is stopping you from choosing specific methods to Serialize:
95
96   sub foo :Local :ActionClass('Serialize') {
97      .. populate stash with data ..
98   }
99
100 When you use this module, the request class will be changed to
101 L<Catalyst::Request::REST>.
102
103 =head1 CONFIGURATION
104
105 =over 4
106
107 =item default
108
109 The Content-Type of the default Serialization format.  This must be a
110 Content-Type associated with a plugin in the "map" section below.  
111
112 This is used if a requested content-type is not recognized.
113
114 =item stash_key 
115
116 We will serialize the data that lives in this location in the stash.  So
117 if the value is "rest", we will serialize the data under:
118
119   $c->stash->{'rest'}
120
121 =item map
122
123 Takes a hashref, mapping Content-Types to a given plugin.
124
125 =back
126
127 =head1 HELPFUL PEOPLE
128
129 Daisuke Maki pointed out that early versions of this Action did not play
130 well with others, or generally behave in a way that was very consistent
131 with the rest of Catalyst. 
132
133 =head1 SEE ALSO
134
135 You likely want to look at L<Catalyst::Controller::REST>, which implements
136 a sensible set of defaults for doing a REST controller.
137
138 L<Catalyst::Action::Deserialize>, L<Catalyst::Action::REST>
139
140 =head1 AUTHOR
141
142 Adam Jacob <adam@stalecoffee.org>, with lots of help from mst and jrockway
143
144 Marchex, Inc. paid me while I developed this module.  (http://www.marchex.com)
145
146 =head1 LICENSE
147
148 You may distribute this code under the same terms as Perl itself.
149
150 =cut
151