1Catalyst::Controller::RUEsSeTr(3C)ontributed Perl DocumeCnattaatliyosnt::Controller::REST(3)
2
3
4

NAME

6       Catalyst::Controller::REST - A RESTful controller
7

SYNOPSIS

9           package Foo::Controller::Bar;
10           use Moose;
11           use namespace::autoclean;
12
13           BEGIN { extends 'Catalyst::Controller::REST' }
14
15           sub thing : Local : ActionClass('REST') { }
16
17           # Answer GET requests to "thing"
18           sub thing_GET {
19              my ( $self, $c ) = @_;
20
21              # Return a 200 OK, with the data in entity
22              # serialized in the body
23              $self->status_ok(
24                   $c,
25                   entity => {
26                       some => 'data',
27                       foo  => 'is real bar-y',
28                   },
29              );
30           }
31
32           # Answer PUT requests to "thing"
33           sub thing_PUT {
34               my ( $self, $c ) = @_;
35
36               $radiohead = $c->req->data->{radiohead};
37
38               $self->status_created(
39                   $c,
40                   location => $c->req->uri,
41                   entity => {
42                       radiohead => $radiohead,
43                   }
44               );
45           }
46

DESCRIPTION

48       Catalyst::Controller::REST implements a mechanism for building RESTful
49       services in Catalyst.  It does this by extending the normal Catalyst
50       dispatch mechanism to allow for different subroutines to be called
51       based on the HTTP Method requested, while also transparently handling
52       all the serialization/deserialization for you.
53
54       This is probably best served by an example.  In the above controller,
55       we have declared a Local Catalyst action on "sub thing", and have used
56       the ActionClass('REST').
57
58       Below, we have declared "thing_GET" and "thing_PUT".  Any GET requests
59       to thing will be dispatched to "thing_GET", while any PUT requests will
60       be dispatched to "thing_PUT".
61
62       Any unimplemented HTTP methods will be met with a "405 Method Not
63       Allowed" response, automatically containing the proper list of
64       available methods.  You can override this behavior through implementing
65       a custom "thing_not_implemented" method.
66
67       If you do not provide an OPTIONS handler, we will respond to any
68       OPTIONS requests with a "200 OK", populating the Allowed header
69       automatically.
70
71       Any data included in "$c->stash->{'rest'}" will be serialized for you.
72       The serialization format will be selected based on the content-type of
73       the incoming request.  It is probably easier to use the "STATUS
74       HELPERS", which are described below.
75
76       "The HTTP POST, PUT, and OPTIONS methods will all automatically
77       deserialize the contents of "$c->request->body" into the
78       "$c->request->data" hashref", based on the request's "Content-type"
79       header. A list of understood serialization formats is below.
80
81       If we do not have (or cannot run) a serializer for a given content-
82       type, a 415 "Unsupported Media Type" error is generated.
83
84       To make your Controller RESTful, simply have it
85
86         BEGIN { extends 'Catalyst::Controller::REST' }
87

CONFIGURATION

89       See "CONFIGURATION" in Catalyst::Action::Serialize. Note that the
90       "serialize" key has been deprecated.
91

SERIALIZATION

93       Catalyst::Controller::REST will automatically serialize your responses,
94       and deserialize any POST, PUT or OPTIONS requests. It evaluates which
95       serializer to use by mapping a content-type to a Serialization module.
96       We select the content-type based on:
97
98       The Content-Type Header
99           If the incoming HTTP Request had a Content-Type header set, we will
100           use it.
101
102       The content-type Query Parameter
103           If this is a GET request, you can supply a content-type query
104           parameter.
105
106       Evaluating the Accept Header
107           Finally, if the client provided an Accept header, we will evaluate
108           it and use the best-ranked choice.
109

AVAILABLE SERIALIZERS

111       A given serialization mechanism is only available if you have the
112       underlying modules installed.  For example, you can't use XML::Simple
113       if it's not already installed.
114
115       In addition, each serializer has its quirks in terms of what sorts of
116       data structures it will properly handle.  Catalyst::Controller::REST
117       makes no attempt to save you from yourself in this regard. :)
118
119       · "text/x-yaml" => "YAML::Syck"
120
121         Returns YAML generated by YAML::Syck.
122
123       · "text/html" => "YAML::HTML"
124
125         This uses YAML::Syck and URI::Find to generate YAML with all URLs
126         turned to hyperlinks.  Only usable for Serialization.
127
128       · "application/json" => "JSON"
129
130         Uses JSON to generate JSON output.  It is strongly advised to also
131         have JSON::XS installed.  The "text/x-json" content type is supported
132         but is deprecated and you will receive warnings in your log.
133
134         You can also add a hash in your controller config to pass options to
135         the json object.  There are two options. "json_options" are used when
136         decoding incoming JSON, and "json_options_encode" is used when
137         encoding JSON for output.
138
139         For instance, to relax permissions when deserializing input, add:
140
141           __PACKAGE__->config(
142             json_options => { relaxed => 1 }
143           )
144
145         To indent the JSON output so it becomes more human readable, add:
146
147           __PACKAGE__->config(
148             json_options_encode => { indent => 1 }
149           )
150
151       · "text/javascript" => "JSONP"
152
153         If a callback=? parameter is passed, this returns javascript in the
154         form of: $callback($serializedJSON);
155
156         Note - this is disabled by default as it can be a security risk if
157         you are unaware.
158
159         The usual MIME types for this serialization format are:
160         'text/javascript', 'application/x-javascript',
161         'application/javascript'.
162
163       · "text/x-data-dumper" => "Data::Serializer"
164
165         Uses the Data::Serializer module to generate Data::Dumper output.
166
167       · "text/x-data-denter" => "Data::Serializer"
168
169         Uses the Data::Serializer module to generate Data::Denter output.
170
171       · "text/x-data-taxi" => "Data::Serializer"
172
173         Uses the Data::Serializer module to generate Data::Taxi output.
174
175       · "text/x-config-general" => "Data::Serializer"
176
177         Uses the Data::Serializer module to generate Config::General output.
178
179       · "text/x-php-serialization" => "Data::Serializer"
180
181         Uses the Data::Serializer module to generate PHP::Serialization
182         output.
183
184       · "text/xml" => "XML::Simple"
185
186         Uses XML::Simple to generate XML output.  This is probably not
187         suitable for any real heavy XML work. Due to XML::Simples requirement
188         that the data you serialize be a HASHREF, we transform outgoing data
189         to be in the form of:
190
191           { data => $yourdata }
192
193       · View
194
195         Uses a regular Catalyst view.  For example, if you wanted to have
196         your "text/html" and "text/xml" views rendered by TT, set:
197
198           __PACKAGE__->config(
199               map => {
200                   'text/html' => [ 'View', 'TT' ],
201                   'text/xml'  => [ 'View', 'XML' ],
202               }
203           );
204
205         Your views should have a "process" method like this:
206
207           sub process {
208               my ( $self, $c, $stash_key ) = @_;
209
210               my $output;
211               eval {
212                   $output = $self->serialize( $c->stash->{$stash_key} );
213               };
214               return $@ if $@;
215
216               $c->response->body( $output );
217               return 1;  # important
218           }
219
220           sub serialize {
221               my ( $self, $data ) = @_;
222
223               my $serialized = ... process $data here ...
224
225               return $serialized;
226           }
227
228       · Callback
229
230         For infinite flexibility, you can provide a callback for the
231         deserialization/serialization steps.
232
233           __PACKAGE__->config(
234               map => {
235                   'text/xml'  => [ 'Callback', { deserialize => \&parse_xml, serialize => \&render_xml } ],
236               }
237           );
238
239         The "deserialize" callback is passed a string that is the body of the
240         request and is expected to return a scalar value that results from
241         the deserialization.  The "serialize" callback is passed the data
242         structure that needs to be serialized and must return a string
243         suitable for returning in the HTTP response.  In addition to
244         receiving the scalar to act on, both callbacks are passed the
245         controller object and the context (i.e. $c) as the second and third
246         arguments.
247
248       By default, Catalyst::Controller::REST will return a "415 Unsupported
249       Media Type" response if an attempt to use an unsupported content-type
250       is made.  You can ensure that something is always returned by setting
251       the "default" config option:
252
253         __PACKAGE__->config(default => 'text/x-yaml');
254
255       would make it always fall back to the serializer plugin defined for
256       "text/x-yaml".
257

CUSTOM SERIALIZERS

259       Implementing new Serialization formats is easy!  Contributions are most
260       welcome!  If you would like to implement a custom serializer, you
261       should create two new modules in the Catalyst::Action::Serialize and
262       Catalyst::Action::Deserialize namespace.  Then assign your new class to
263       the content-type's you want, and you're done.
264
265       See Catalyst::Action::Serialize and Catalyst::Action::Deserialize for
266       more information.
267

STATUS HELPERS

269       Since so much of REST is in using HTTP, we provide these Status
270       Helpers.  Using them will ensure that you are responding with the
271       proper codes, headers, and entities.
272
273       These helpers try and conform to the HTTP 1.1 Specification.  You can
274       refer to it at: <http://www.w3.org/Protocols/rfc2616/rfc2616.txt>.
275       These routines are all implemented as regular subroutines, and as such
276       require you pass the current context ($c) as the first argument.
277
278       status_ok
279           Returns a "200 OK" response.  Takes an "entity" to serialize.
280
281           Example:
282
283             $self->status_ok(
284               $c,
285               entity => {
286                   radiohead => "Is a good band!",
287               }
288             );
289
290       status_created
291           Returns a "201 CREATED" response.  Takes an "entity" to serialize,
292           and a "location" where the created object can be found.
293
294           Example:
295
296             $self->status_created(
297               $c,
298               location => $c->req->uri,
299               entity => {
300                   radiohead => "Is a good band!",
301               }
302             );
303
304           In the above example, we use the requested URI as our location.
305           This is probably what you want for most PUT requests.
306
307       status_accepted
308           Returns a "202 ACCEPTED" response.  Takes an "entity" to serialize.
309           Also takes optional "location" for queue type scenarios.
310
311           Example:
312
313             $self->status_accepted(
314               $c,
315               location => $c->req->uri,
316               entity => {
317                   status => "queued",
318               }
319             );
320
321       status_no_content
322           Returns a "204 NO CONTENT" response.
323
324       status_multiple_choices
325           Returns a "300 MULTIPLE CHOICES" response. Takes an "entity" to
326           serialize, which should provide list of possible locations. Also
327           takes optional "location" for preferred choice.
328
329       status_found
330           Returns a "302 FOUND" response. Takes an "entity" to serialize.
331           Also takes optional "location".
332
333       status_bad_request
334           Returns a "400 BAD REQUEST" response.  Takes a "message" argument
335           as a scalar, which will become the value of "error" in the
336           serialized response.
337
338           Example:
339
340             $self->status_bad_request(
341               $c,
342               message => "Cannot do what you have asked!",
343             );
344
345       status_forbidden
346           Returns a "403 FORBIDDEN" response.  Takes a "message" argument as
347           a scalar, which will become the value of "error" in the serialized
348           response.
349
350           Example:
351
352             $self->status_forbidden(
353               $c,
354               message => "access denied",
355             );
356
357       status_not_found
358           Returns a "404 NOT FOUND" response.  Takes a "message" argument as
359           a scalar, which will become the value of "error" in the serialized
360           response.
361
362           Example:
363
364             $self->status_not_found(
365               $c,
366               message => "Cannot find what you were looking for!",
367             );
368
369       gone
370           Returns a "41O GONE" response.  Takes a "message" argument as a
371           scalar, which will become the value of "error" in the serialized
372           response.
373
374           Example:
375
376             $self->status_gone(
377               $c,
378               message => "The document have been deleted by foo",
379             );
380
381       status_see_other
382           Returns a "303 See Other" response.  Takes an optional "entity" to
383           serialize, and a "location" where the client should redirect to.
384
385           Example:
386
387             $self->status_see_other(
388               $c,
389               location => $some_other_url,
390               entity => {
391                   radiohead => "Is a good band!",
392               }
393             );
394
395       status_moved
396           Returns a "301 MOVED" response.  Takes an "entity" to serialize,
397           and a "location" where the created object can be found.
398
399           Example:
400
401            $self->status_moved(
402              $c,
403              location => '/somewhere/else',
404              entity => {
405                radiohead => "Is a good band!",
406              },
407            );
408

MANUAL RESPONSES

410       If you want to construct your responses yourself, all you need to do is
411       put the object you want serialized in $c->stash->{'rest'}.
412

IMPLEMENTATION DETAILS

414       This Controller ties together Catalyst::Action::REST,
415       Catalyst::Action::Serialize and Catalyst::Action::Deserialize.  It
416       should be suitable for most applications.  You should be aware that it:
417
418       Configures the Serialization Actions
419           This class provides a default configuration for Serialization.  It
420           is currently:
421
422             __PACKAGE__->config(
423                 'stash_key' => 'rest',
424                 'map'       => {
425                    'text/html'          => 'YAML::HTML',
426                    'text/xml'           => 'XML::Simple',
427                    'text/x-yaml'        => 'YAML',
428                    'application/json'   => 'JSON',
429                    'text/x-json'        => 'JSON',
430                    'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
431                    'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ],
432                    'text/x-data-taxi'   => [ 'Data::Serializer', 'Data::Taxi'   ],
433                    'application/x-storable'   => [ 'Data::Serializer', 'Storable' ],
434                    'application/x-freezethaw' => [ 'Data::Serializer', 'FreezeThaw' ],
435                    'text/x-config-general'    => [ 'Data::Serializer', 'Config::General' ],
436                    'text/x-php-serialization' => [ 'Data::Serializer', 'PHP::Serialization' ],
437                 },
438             );
439
440           You can read the full set of options for this configuration block
441           in Catalyst::Action::Serialize.
442
443       Sets a "begin" and "end" method for you
444           The "begin" method uses Catalyst::Action::Deserialize.  The "end"
445           method uses Catalyst::Action::Serialize.  If you want to override
446           either behavior, simply implement your own "begin" and "end"
447           actions and forward to another action with the Serialize and/or
448           Deserialize action classes:
449
450             package Foo::Controller::Monkey;
451             use Moose;
452             use namespace::autoclean;
453
454             BEGIN { extends 'Catalyst::Controller::REST' }
455
456             sub begin : Private {
457               my ($self, $c) = @_;
458               ... do things before Deserializing ...
459               $c->forward('deserialize');
460               ... do things after Deserializing ...
461             }
462
463             sub deserialize : ActionClass('Deserialize') {}
464
465             sub end :Private {
466               my ($self, $c) = @_;
467               ... do things before Serializing ...
468               $c->forward('serialize');
469               ... do things after Serializing ...
470             }
471
472             sub serialize : ActionClass('Serialize') {}
473
474           If you need to deserialize multipart requests (i.e. REST data in
475           one part and file uploads in others) you can do so by using the
476           Catalyst::Action::DeserializeMultiPart action class.
477

A MILD WARNING

479       I have code in production using Catalyst::Controller::REST.  That said,
480       it is still under development, and it's possible that things may change
481       between releases.  I promise to not break things unnecessarily. :)
482

SEE ALSO

484       Catalyst::Action::REST, Catalyst::Action::Serialize,
485       Catalyst::Action::Deserialize
486
487       For help with REST in general:
488
489       The HTTP 1.1 Spec is required reading.
490       http://www.w3.org/Protocols/rfc2616/rfc2616.txt
491
492       Wikipedia! http://en.wikipedia.org/wiki/Representational_State_Transfer
493
494       The REST Wiki: http://rest.blueoxen.net/cgi-bin/wiki.pl?FrontPage
495

AUTHORS

497       See Catalyst::Action::REST for authors.
498

LICENSE

500       You may distribute this code under the same terms as Perl itself.
501
502
503
504perl v5.28.0                      2017-12-05     Catalyst::Controller::REST(3)
Impressum