The document provides an overview of REST and how it can be implemented using the Catalyst framework in Perl. It discusses what REST is, how it leverages existing aspects of HTTP like verbs and status codes, and isn't a defined protocol but a set of best practices. It then describes the Catalyst::Action::REST module which makes it easy to build RESTful APIs in Catalyst and supports various serialization formats. Examples are given of performing CRUD operations via REST calls from the command line and how to handle this in browsers using JavaScript and YUI.
7. What Isn’t REST
A defined protocol
A tool for every job
Good for browsers
Since IE7, most browsers work with XmlHttpRequest
Various hacks exist to DTRT
4
8. HTTP does a lot
Common “verbs” for CRUD:
Create an object (POST)
Retrieve an object (GET)
Update an object (PUT)
Delete an object (DELETE)
(And more, but that’s another story)
5
11. What about pretty URIs?
Pretty URI ≠ REST
Functional URI = REST
/item/B9B6F0F8-1DE5-11DD-9305-CB9FBFD82403
(still REST)
Pretty for the computer, not for you.
7
12. So, REST is
Using as much of the HTTP spec as you can
With URIs that...
8
13. So, REST is
Using as much of the HTTP spec as you can
With URIs that...
Mean something (Represent a resource or object)
8
14. So, REST is
Using as much of the HTTP spec as you can
With URIs that...
Mean something (Represent a resource or object)
Don’t have to be pretty
8
15. So, REST is
Using as much of the HTTP spec as you can
With URIs that...
Mean something (Represent a resource or object)
Don’t have to be pretty
Don’t have to be ugly
8
22. The response should
respect the request.
“Accept” determines what serialization format
(and “Content-Type”)
14
23. The response should
respect the request.
“Accept” determines what serialization format
(and “Content-Type”)
“Accept-Language” determines what language
14
24. The response should
respect the request.
“Accept” determines what serialization format
(and “Content-Type”)
“Accept-Language” determines what language
“Accept-Charset” determines what charset
14
25. The response should
respect the request.
“Accept” determines what serialization format
(and “Content-Type”)
“Accept-Language” determines what language
“Accept-Charset” determines what charset
Listed in order of preference from the client.
14
29. And to help out...
Catalyst::Controller::REST::DBIC::Item
• I couldn’t think of a longer name
• Just a base class for yak shaving
• Links DBIx::Class result sets to REST actions
• Almost CRUD, except just scaffolding for it
• Only a dev release on CPAN
(only thing fancy about it is this slide)
17
30. A Use Case
http://www.iwatchsoccer.com/
A simple site to list upcoming soccer matches.
Uses Catalyst, REST and DBIx::Class
18
31. Very small
Team League
Four Basic Objects:
Game Game
19
32. And some links
A game has many broadcasts
Networks have many broadcasts
A game belongs to a league
A team has many leagues
20
33. Using REST
Still works in a web browser
Serializes response through Template Toolkit
Handles GET only (but doesn’t have to)
21
35. Handling other verbs
POST, PUT, DELETE via simple commands:
$ POST -c ‘text/x-yaml’ http://localhost:3000/team
22
36. Handling other verbs
POST, PUT, DELETE via simple commands:
$ POST -c ‘text/x-yaml’ http://localhost:3000/team
Please enter content (text/x-yaml) to be POSTed:
---
display_name: Urawa Red Diamonds
22
39. Same idea for GET
$ GET -H ‘Content-type: text/x-yaml’
http://localhost:3000/team
24
40. Same idea for GET
$ GET -H ‘Content-type: text/x-yaml’
http://localhost:3000/team
---
-
display_name: Urawa Red Diamonds
pk1: 7
token_name: urawa-red-diamonds
24
43. Just change Content-type
$ GET -H ‘Content-type: text/x-json’
http://localhost:3000/team
[{quot;token_namequot;:quot;urawa-red-
diamondsquot;,quot;display_namequot;:quot;Urawa Red
Diamondsquot;,quot;pk1quot;:7}]
25
45. Not just YAML
Many serialization formats, from Catalyst::Action::REST
26
46. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
26
47. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
JSON
26
48. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
JSON
XML::Simple
26
49. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
JSON
XML::Simple
Data::Serializer
26
50. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
JSON
XML::Simple
Data::Serializer
Any Catalyst View
26
51. Not just YAML
Many serialization formats, from Catalyst::Action::REST
YAML
JSON
XML::Simple
Data::Serializer
Any Catalyst View
Easy to write your own
26
58. Starting the chain
Two actions:
sub rest_base : Chained(‘/’) PathPart(‘rest’)
CaptureArgs(0) { }
# Automatically defined by
Catalyst::Controller::REST::DBIC::Item
sub rest_item : Chained(‘rest_base’) PathPart(‘item’)
CaptureArgs(1) { }
31
59. What you really need:
package IWS::Controller::Team;
use strict;
use warnings;
use base 'Catalyst::Controller::REST::DBIC::Item';
__PACKAGE__->config(
# snipped general REST config
'class' => 'Schema::Team',
'item_key' => 'token_name',
'serialize_method' => 'serialize',
'browser_serialize' => 0
);
sub rest_base : Chained('/') PathPart('') CaptureArgs(0){ }
32
60. Simple Controllers
sub rest_item_POST {
my ( $self, $c ) = @_;
my $data = $c->request->data;
my $row = $self->get_rs( $c )->find_or_create($data);
if ( $row ) {
$self->status_created( $c, ... );
} else {
$self->status_bad_request( $c, ... );
}
}
(but please, validate $data)
33
63. Dispatching REST Actions
Chain is:
rest_base -> rest_item -> rest_item_${METHOD}
GET /rest/item/foo
calls rest_item_GET
34
64. Dispatching REST Actions
Chain is:
rest_base -> rest_item -> rest_item_${METHOD}
GET /rest/item/foo
calls rest_item_GET
PUT /rest/item/foo
34
65. Dispatching REST Actions
Chain is:
rest_base -> rest_item -> rest_item_${METHOD}
GET /rest/item/foo
calls rest_item_GET
PUT /rest/item/foo
calls rest_item_PUT
34
66. Dispatching REST Actions
Chain is:
rest_base -> rest_item -> rest_item_${METHOD}
GET /rest/item/foo
calls rest_item_GET
PUT /rest/item/foo
calls rest_item_PUT
All from Catalyst::Action::REST
34
67. Simple Controllers
sub rest_item_DELETE {
my ( $self, $c ) = @_;
my $item = $c->stash->{rest}->{item};
$item->delete;
return $self->status_accepted( $c,
entity => { status => ‘deleted’ }
);
}
35
70. More Bling
Browsers and REST do not play well...
Except inside of XmlHttpRequest
With IE7, they all play well
36
71. More Bling
Browsers and REST do not play well...
Except inside of XmlHttpRequest
With IE7, they all play well
Full support of POST, PUT, GET and DELETE
36
77. Still easy.
Set the content-type:
YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);
41
78. Still easy.
Set the content-type:
YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);
Stringify the data:
YAHOO.lang.JSON.stringify(data)
41
79. Still easy.
Set the content-type:
YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);
Stringify the data:
YAHOO.lang.JSON.stringify(data)
Done
41
80. Connecting to a form
A few points:
Form action does not need to be what you use in
JavaScript
Form method does not need to be what you use in
JavaScript
42
81. YAHOO.util.Event
var form = YAHOO.util.Dom.get(‘form_id’);
YAHOO.util.Event.on( form, ‘submit’, function() {
});
43
82. That’s it
Serialize form data into JSON
Do PUT, POST, DELETE, GET on form submit
REST
44
83. A word on JSON
JSON is not:
Supposed to be eval’d
Just JavaScript
45
84. A word on JSON
JSON is not:
Supposed to be eval’d
Just JavaScript
JSON is:
Very Fast (JSON::XS and JSON::PC)
Very Small
45