1 package Catalyst::Action::Deserialize;
4 use namespace::autoclean;
6 extends 'Catalyst::Action::SerializeBase';
7 use Module::Pluggable::Object;
9 use Moose::Util::TypeConstraints;
11 has plugins => ( is => 'rw' );
13 has deserialize_http_methods => (
16 my $tc = subtype as 'HashRef[Str]';
17 coerce $tc, from 'ArrayRef[Str]',
18 via { +{ map { ($_ => 1) } @$_ } };
22 builder => '_build_deserialize_http_methods',
24 deserialize_http_methods => 'keys',
25 _deserialize_handles_http_method => 'exists',
29 sub _build_deserialize_http_methods { [qw(POST PUT OPTIONS DELETE)] }
33 my ( $controller, $c ) = @_;
35 if ( !defined($c->req->data) && $self->_deserialize_handles_http_method($c->request->method) ) {
36 my ( $sclass, $sarg, $content_type ) =
37 $self->_load_content_plugins( 'Catalyst::Action::Deserialize',
39 return 1 unless defined($sclass);
41 if ( defined($sarg) ) {
42 $rc = $sclass->execute( $controller, $c, $sarg );
44 $rc = $sclass->execute( $controller, $c );
47 return $self->unsupported_media_type( $c, $content_type );
48 } elsif ( $rc ne "1" ) {
49 return $self->serialize_bad_request( $c, $content_type, $rc );
53 $self->maybe::next::method(@_);
58 __PACKAGE__->meta->make_immutable;
62 Catalyst::Action::Deserialize - Deserialize Data in a Request
66 package Foo::Controller::Bar;
69 'default' => 'text/x-yaml',
70 'stash_key' => 'rest',
72 'text/x-yaml' => 'YAML',
73 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
77 sub begin :ActionClass('Deserialize') {}
81 This action will deserialize HTTP POST, PUT, OPTIONS and DELETE requests.
82 It assumes that the body of the HTTP Request is a serialized object.
83 The serializer is selected by introspecting the requests content-type
86 If you want deserialize any other HTTP method besides POST, PUT,
87 OPTIONS and DELETE you can do this by setting the
88 C<< deserialize_http_methods >> list via C<< action_args >>.
89 Just modify the config in your controller and define a list of HTTP
90 methods the deserialization should happen for:
95 deserialize_http_methods => [qw(POST PUT OPTIONS DELETE GET)]
100 See also L<Catalyst::Controller/action_args>.
102 The specifics of deserializing each content-type is implemented as
103 a plugin to L<Catalyst::Action::Deserialize>. You can see a list
104 of currently implemented plugins in L<Catalyst::Controller::REST>.
106 The results of your Deserializing will wind up in $c->req->data.
107 This is done through the magic of L<Catalyst::Request::REST>.
109 While it is common for this Action to be called globally as a
110 C<begin> method, there is nothing stopping you from using it on a
113 sub foo :Local :Action('Deserialize') {}
117 When you use this module, the request class will be changed to
118 L<Catalyst::Request::REST>.
120 =head1 RFC 7231 Compliance Mode
122 To maintain backwards compatibility with the module's original functionality,
123 where it was assumed the deserialize and serialize content types are the same,
124 an optional compliance mode can be enabled to break this assumption.
127 'compliance_mode' => 1,
128 'default' => 'text/x-yaml',
129 'stash_key' => 'rest',
131 'text/x-yaml' => 'YAML',
132 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
134 'deserialize_default => 'application/json',
135 'deserialize_map' => {
136 'application/json' => 'JSON',
140 Three extra keys are added to the controller configuration. compliance_mode, a
141 boolean to enable the mode. And a parallel set of content type mappings
142 'deserialize_default' and 'deserialize_map' to mirror the default/map
145 The module will use the default/map keys when negotiating the serializing
146 content type specified by the client in the Accept header. And will use the
147 deserialize_default/deserialize_map in conjunction with the Content-Type
148 header where the client is giving the content type being sent in the request.
152 For building custom error responses when de-serialization fails, you can create
153 an ActionRole (and use L<Catalyst::Controller::ActionRole> to apply it to the
154 C<begin> action) which overrides C<unsupported_media_type> and/or C<serialize_bad_request>
159 You likely want to look at L<Catalyst::Controller::REST>, which implements
160 a sensible set of defaults for a controller doing REST.
162 L<Catalyst::Action::Serialize>, L<Catalyst::Action::REST>
166 See L<Catalyst::Action::REST> for authors.
170 You may distribute this code under the same terms as Perl itself.