no rest for the wicked: rest and catalyst

84
No REST for the Wicked An overview of REST and Catalyst By Jay Shirley < [email protected] > 1

Upload: jay-shirley

Post on 17-May-2015

10.084 views

Category:

Technology


3 download

DESCRIPTION

Jay Shirley's talk on REST and Catalyst at YAPC::Asia

TRANSCRIPT

Page 1: No REST for the Wicked: REST and Catalyst

No REST for the WickedAn overview of REST and CatalystBy Jay Shirley <[email protected]>

1

Page 2: No REST for the Wicked: REST and Catalyst

REST in 5 Minutes

No Dragons Here

2

Page 3: No REST for the Wicked: REST and Catalyst

What Is REST?

Using more of HTTP 1.1

3

Page 4: No REST for the Wicked: REST and Catalyst

What Is REST?

Using more of HTTP 1.1

A set of ideas

Most are good

Most are easy

3

Page 5: No REST for the Wicked: REST and Catalyst

What Isn’t REST

A defined protocol

4

Page 6: No REST for the Wicked: REST and Catalyst

What Isn’t REST

A defined protocol

A tool for every job

4

Page 7: No REST for the Wicked: REST and Catalyst

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

Page 8: No REST for the Wicked: REST and Catalyst

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

Page 9: No REST for the Wicked: REST and Catalyst

HTTP is Extensible

HTTP Headers:

Content-type

X-Your-Header

X-AuthToken

X-REST-Tunnel-Method (for dumb browsers)

6

Page 10: No REST for the Wicked: REST and Catalyst

What about pretty URIs?

Pretty URI ≠ REST

7

Page 11: No REST for the Wicked: REST and Catalyst

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

Page 12: No REST for the Wicked: REST and Catalyst

So, REST is

Using as much of the HTTP spec as you can

With URIs that...

8

Page 13: No REST for the Wicked: REST and Catalyst

So, REST is

Using as much of the HTTP spec as you can

With URIs that...

Mean something (Represent a resource or object)

8

Page 14: No REST for the Wicked: REST and Catalyst

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

Page 15: No REST for the Wicked: REST and Catalyst

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

Page 16: No REST for the Wicked: REST and Catalyst

Oh, and...

Stateless

9

Page 17: No REST for the Wicked: REST and Catalyst

Stateless?

Client holds the state

Transactions get tricky

Implicit trust of the client

Trouble for web applications

10

Page 18: No REST for the Wicked: REST and Catalyst

Using REST

All or nothing? No, a la carte.

Not a standard; just good ideas

Use only what you need

11

Page 19: No REST for the Wicked: REST and Catalyst

REST in more minutes...

12

Page 20: No REST for the Wicked: REST and Catalyst

REST is in the Request

Typical browser request:Host: iwatchsoccer.comUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9b5) Gecko/2008032619 Firefox/3.0b5Accept: HTTP Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Keep-Alive: 300Connection: keep-alive

13

Page 21: No REST for the Wicked: REST and Catalyst

The response should respect the request.

14

Page 22: No REST for the Wicked: REST and Catalyst

The response should respect the request.

“Accept” determines what serialization format(and “Content-Type”)

14

Page 23: No REST for the Wicked: REST and Catalyst

The response should respect the request.

“Accept” determines what serialization format(and “Content-Type”)

“Accept-Language” determines what language

14

Page 24: No REST for the Wicked: REST and Catalyst

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

Page 25: No REST for the Wicked: REST and Catalyst

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

Page 26: No REST for the Wicked: REST and Catalyst

And now for Catalyst

15

Page 27: No REST for the Wicked: REST and Catalyst

Catalyst::Action::REST

Available from CPAN

Handles:

Accept (Response Format)

Request (GET, PUT, POST, DELETE)

Easy to configure

Works great

16

Page 28: No REST for the Wicked: REST and Catalyst

And to help out...

17

Page 29: No REST for the Wicked: REST and Catalyst

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

Page 30: No REST for the Wicked: REST and Catalyst

A Use Case

http://www.iwatchsoccer.com/

A simple site to list upcoming soccer matches.

Uses Catalyst, REST and DBIx::Class

18

Page 31: No REST for the Wicked: REST and Catalyst

Very small

Four Basic Objects:

Team League

Game Game

19

Page 32: No REST for the Wicked: REST and Catalyst

And some links

A game has many broadcasts

Networks have many broadcasts

A game belongs to a league

A team has many leagues

20

Page 33: No REST for the Wicked: REST and Catalyst

Using REST

Still works in a web browser

Serializes response through Template Toolkit

Handles GET only (but doesn’t have to)

21

Page 34: No REST for the Wicked: REST and Catalyst

Handling other verbs

POST, PUT, DELETE via simple commands:

22

Page 35: No REST for the Wicked: REST and Catalyst

Handling other verbs

POST, PUT, DELETE via simple commands:

$ POST -c ‘text/x-yaml’ http://localhost:3000/team

22

Page 36: No REST for the Wicked: REST and Catalyst

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

Page 37: No REST for the Wicked: REST and Catalyst

Perl:

my $lwp = LWP::UserAgent->new;$lwp->post( "http://localhost:3000/team",'Content-type' => 'text/x-yaml',

Content => YAML::Syck::Dump($team));

23

Page 38: No REST for the Wicked: REST and Catalyst

Same idea for GET

24

Page 39: No REST for the Wicked: REST and Catalyst

Same idea for GET

$ GET -H ‘Content-type: text/x-yaml’ \http://localhost:3000/team

24

Page 40: No REST for the Wicked: REST and Catalyst

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

Page 41: No REST for the Wicked: REST and Catalyst

Just change Content-type

25

Page 42: No REST for the Wicked: REST and Catalyst

Just change Content-type

$ GET -H ‘Content-type: text/x-json’ \http://localhost:3000/team

25

Page 43: No REST for the Wicked: REST and Catalyst

Just change Content-type

$ GET -H ‘Content-type: text/x-json’ \http://localhost:3000/team

[{"token_name":"urawa-red-diamonds","display_name":"Urawa Red Diamonds","pk1":7}]

25

Page 44: No REST for the Wicked: REST and Catalyst

Not just YAML

26

Page 45: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

26

Page 46: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

YAML

26

Page 47: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

YAML

JSON

26

Page 48: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

YAML

JSON

XML::Simple

26

Page 49: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

YAML

JSON

XML::Simple

Data::Serializer

26

Page 50: No REST for the Wicked: REST and Catalyst

Not just YAML

Many serialization formats, from Catalyst::Action::REST

YAML

JSON

XML::Simple

Data::Serializer

Any Catalyst View

26

Page 51: No REST for the Wicked: REST and Catalyst

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

Page 52: No REST for the Wicked: REST and Catalyst

And, of course, HTML

27

Page 53: No REST for the Wicked: REST and Catalyst

Template Toolkit:

“Serialization”

28

Page 54: No REST for the Wicked: REST and Catalyst

All through configuration:

package MyApp::Controller::RestClass;...__PACKAGE__->config( 'default' => 'text/html', 'map' => { 'text/html' => [ 'View', 'TT' ], 'text/xml' => [ 'View', 'TT' ] });

29

Page 55: No REST for the Wicked: REST and Catalyst

The REST Chain

Catalyst::DispatchType::Chained

30

Page 56: No REST for the Wicked: REST and Catalyst

The REST Chain

Catalyst::DispatchType::Chained

Very powerful

30

Page 57: No REST for the Wicked: REST and Catalyst

The REST Chain

Catalyst::DispatchType::Chained

Very powerful

Not what this talk is about

30

Page 58: No REST for the Wicked: REST and Catalyst

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

Page 59: No REST for the Wicked: REST and Catalyst

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

Page 60: No REST for the Wicked: REST and Catalyst

Simple Controllerssub 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

Page 61: No REST for the Wicked: REST and Catalyst

Dispatching REST Actions

Chain is:rest_base -> rest_item -> rest_item_${METHOD}

34

Page 62: No REST for the Wicked: REST and Catalyst

Dispatching REST Actions

Chain is:rest_base -> rest_item -> rest_item_${METHOD}

GET /rest/item/foo

34

Page 63: No REST for the Wicked: REST and Catalyst

Dispatching REST Actions

Chain is:rest_base -> rest_item -> rest_item_${METHOD}

GET /rest/item/foo

calls rest_item_GET

34

Page 64: No REST for the Wicked: REST and Catalyst

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

Page 65: No REST for the Wicked: REST and Catalyst

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

Page 66: No REST for the Wicked: REST and Catalyst

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

Page 67: No REST for the Wicked: REST and Catalyst

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

Page 68: No REST for the Wicked: REST and Catalyst

More Bling

Browsers and REST do not play well...

36

Page 69: No REST for the Wicked: REST and Catalyst

More Bling

Browsers and REST do not play well...

Except inside of XmlHttpRequest

36

Page 70: No REST for the Wicked: REST and Catalyst

More Bling

Browsers and REST do not play well...

Except inside of XmlHttpRequest

With IE7, they all play well

36

Page 71: No REST for the Wicked: REST and Catalyst

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

Page 72: No REST for the Wicked: REST and Catalyst

The Solution

http://developer.yahoo.com/yui/

37

Page 73: No REST for the Wicked: REST and Catalyst

Why YUI?

Well supported

Smart hackers that know JavaScript

Smart hackers that know standards

Good documentation, code and primitives

38

Page 74: No REST for the Wicked: REST and Catalyst

YUI REST Commands

YAHOO.util.Connect.asyncRequest(

‘PUT’, uri, callback, data

);

39

Page 75: No REST for the Wicked: REST and Catalyst

Needs a few modifications

YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);

YAHOO.util.Connect.asyncRequest(

‘PUT’, uri, callback, YAHOO.lang.JSON.stringify(data)

);

40

Page 76: No REST for the Wicked: REST and Catalyst

Still easy.

41

Page 77: No REST for the Wicked: REST and Catalyst

Still easy.

Set the content-type:YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);

41

Page 78: No REST for the Wicked: REST and Catalyst

Still easy.

Set the content-type:YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);

Stringify the data:YAHOO.lang.JSON.stringify(data)

41

Page 79: No REST for the Wicked: REST and Catalyst

Still easy.

Set the content-type:YAHOO.util.Connect.setDefaultPostHeader(‘text/x-json’);

Stringify the data:YAHOO.lang.JSON.stringify(data)

Done

41

Page 80: No REST for the Wicked: REST and Catalyst

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

Page 81: No REST for the Wicked: REST and Catalyst

YAHOO.util.Event

var form = YAHOO.util.Dom.get(‘form_id’);

YAHOO.util.Event.on( form, ‘submit’, function() {

});

43

Page 82: No REST for the Wicked: REST and Catalyst

That’s it

Serialize form data into JSON

Do PUT, POST, DELETE, GET on form submit

REST

44

Page 83: No REST for the Wicked: REST and Catalyst

A word on JSON

JSON is not:

Supposed to be eval’d

Just JavaScript

45

Page 84: No REST for the Wicked: REST and Catalyst

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