t push origin masterMerge branch 'bockscar-master'
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / Deserialize.pm
CommitLineData
7ad87df9 1package Catalyst::Action::Deserialize;
2
930013e6 3use Moose;
4use namespace::autoclean;
7ad87df9 5
930013e6 6extends 'Catalyst::Action::SerializeBase';
7ad87df9 7use Module::Pluggable::Object;
def65dcc 8use MRO::Compat;
599755b6 9use Moose::Util::TypeConstraints;
7ad87df9 10
05009b91 11has plugins => ( is => 'rw' );
7ad87df9 12
588cbecc 13has deserialize_http_methods => (
599755b6 14 traits => ['Hash'],
15 isa => do {
16 my $tc = subtype as 'HashRef[Str]';
17 coerce $tc, from 'ArrayRef[Str]',
18 via { +{ map { ($_ => 1) } @$_ } };
19 $tc;
20 },
21 coerce => 1,
588cbecc 22 builder => '_build_deserialize_http_methods',
23 handles => {
599755b6 24 deserialize_http_methods => 'keys',
25 _deserialize_handles_http_method => 'exists',
588cbecc 26 },
27);
28
29sub _build_deserialize_http_methods { [qw(POST PUT OPTIONS DELETE)] }
30
7ad87df9 31sub execute {
32 my $self = shift;
e601adda 33 my ( $controller, $c ) = @_;
7ad87df9 34
5bf53db4 35 if ( !defined($c->req->data) && $self->_deserialize_handles_http_method($c->request->method) ) {
9a76221e 36 my ( $sclass, $sarg, $content_type ) =
37 $self->_load_content_plugins( 'Catalyst::Action::Deserialize',
38 $controller, $c );
39 return 1 unless defined($sclass);
e601adda 40 my $rc;
eccb2137 41 if ( defined($sarg) ) {
e601adda 42 $rc = $sclass->execute( $controller, $c, $sarg );
7ad87df9 43 } else {
e601adda 44 $rc = $sclass->execute( $controller, $c );
45 }
9a76221e 46 if ( $rc eq "0" ) {
b3996af8 47 return $self->unsupported_media_type( $c, $content_type );
9a76221e 48 } elsif ( $rc ne "1" ) {
b3996af8 49 return $self->serialize_bad_request( $c, $content_type, $rc );
7ad87df9 50 }
9a76221e 51 }
e601adda 52
def65dcc 53 $self->maybe::next::method(@_);
e601adda 54
55 return 1;
eccb2137 56}
7ad87df9 57
05009b91 58__PACKAGE__->meta->make_immutable;
59
398c5a1b 60=head1 NAME
61
62Catalyst::Action::Deserialize - Deserialize Data in a Request
63
64=head1 SYNOPSIS
65
66 package Foo::Controller::Bar;
67
68 __PACKAGE__->config(
faf5c20b 69 'default' => 'text/x-yaml',
70 'stash_key' => 'rest',
71 'map' => {
72 'text/x-yaml' => 'YAML',
73 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
74 },
398c5a1b 75 );
76
e601adda 77 sub begin :ActionClass('Deserialize') {}
398c5a1b 78
79=head1 DESCRIPTION
80
588cbecc 81This action will deserialize HTTP POST, PUT, OPTIONS and DELETE requests.
398c5a1b 82It assumes that the body of the HTTP Request is a serialized object.
83The serializer is selected by introspecting the requests content-type
84header.
85
588cbecc 86If you want deserialize any other HTTP method besides POST, PUT,
87OPTIONS and DELETE you can do this by setting the
88C<< deserialize_http_methods >> list via C<< action_args >>.
89Just modify the config in your controller and define a list of HTTP
90methods the deserialization should happen for:
91
92 __PACKAGE__->config(
93 action_args => {
94 '*' => {
95 deserialize_http_methods => [qw(POST PUT OPTIONS DELETE GET)]
96 }
97 }
98 );
99
100See also L<Catalyst::Controller/action_args>.
101
398c5a1b 102The specifics of deserializing each content-type is implemented as
103a plugin to L<Catalyst::Action::Deserialize>. You can see a list
104of currently implemented plugins in L<Catalyst::Controller::REST>.
105
106The results of your Deserializing will wind up in $c->req->data.
107This is done through the magic of L<Catalyst::Request::REST>.
108
e601adda 109While it is common for this Action to be called globally as a
110C<begin> method, there is nothing stopping you from using it on a
111single routine:
398c5a1b 112
e601adda 113 sub foo :Local :Action('Deserialize') {}
398c5a1b 114
e601adda 115Will work just fine.
398c5a1b 116
9a76221e 117When you use this module, the request class will be changed to
118L<Catalyst::Request::REST>.
119
b3996af8 120=head1 CUSTOM ERRORS
121
122For building custom error responses when de-serialization fails, you can create
123an ActionRole (and use L<Catalyst::Controller::ActionRole> to apply it to the
b74200b3 124C<begin> action) which overrides C<unsupported_media_type> and/or C<serialize_bad_request>
b3996af8 125methods.
126
398c5a1b 127=head1 SEE ALSO
128
129You likely want to look at L<Catalyst::Controller::REST>, which implements
130a sensible set of defaults for a controller doing REST.
131
132L<Catalyst::Action::Serialize>, L<Catalyst::Action::REST>
133
5cb5f6bb 134=head1 AUTHORS
398c5a1b 135
5cb5f6bb 136See L<Catalyst::Action::REST> for authors.
398c5a1b 137
138=head1 LICENSE
139
140You may distribute this code under the same terms as Perl itself.
141
142=cut