Rest

50
REST I am Brian Kaney from Vermonster LLC and will be presenting this talk on REST. http://vermonster.com github/twitter/irc: bkaney

Transcript of Rest

Page 1: Rest

REST

I am Brian Kaney from Vermonster LLC and will be presenting this talk on REST.

http://vermonster.com

github/twitter/irc: bkaney

Page 2: Rest

What is REST?

● Conceived by Roy Fielding, author of the HTTP spec (1.0 and 1.1)

● An architecture (not a spec, not a standard)● Early implementation RFC5023 (Atom RSS)

● Op-ed: Wonderfully constraining way to view the web and conceive web applications

Page 3: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Page 4: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Huh?

Page 5: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Resources: Sources of specifc information

Page 6: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Stateless: Each request has all the information required, any state info is client-side.

Page 7: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

URIs: Identifcation of the representations of the resource.

Page 8: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Uniform Interface: Common standard, like HTTP.

Page 9: Rest

Characteristics

A web architecture where resources are stateless and exposed through (meaningful) URIs, manipulation is through a uniform interface and responses are self-descriptive.

Self-descriptive: Provides enough information as to how to process the response, like the content-type.

Page 10: Rest

You might not be RESTful if...

Using HTTP with standard POST, GET, PUT requests, even with friendly URLs...and you still might not be using REST.

Anti-patterns to look for:● Using GET for non-retrieval● Using POST for “transport protocol”● No-cache● Ignoring status codes● Ignoring MIME and headers● No Hypermedia, link representations

Page 11: Rest

Contrast to RPC

● Remote procedure calls● Not stateless● Not uniform

getCar(), updateCarAttributes(stuff), deleteCarsForManufacturer(mfg)

● Snowball into things like SOAP and WSDL that help automate discovery and describe what they do

● It's very Enterprisey

Page 12: Rest

Contrast to RPC

GET /cars

Page 13: Rest

Contrast to RPC

Once you even nod slightly toward calling remote procedures, you've abandoned the stateless beauty of the web and there is no turning back!!!

Page 14: Rest

Contrast to RPC

Once you even nod slightly toward calling remote procedures, you've abandoned the stateless beauty of the web and there is no turning back!!!

But “foolish consistency is the hobgoblin of little minds”

- Ralph Waldo Emersoni.e. (cookies) – sparingly

Page 15: Rest

Idempotent Operations

Same operation with same parameters

=> same outcome

● Get● Update● Delete

Page 16: Rest

HATEOAS

● Hypermedia as the Engine of Application State

● Roy Fielding (again)● Instead of WSDLs, the hypermedia in

responses describes what can be done

● HATEOAS is a fantastic UI/UX principal for humans too

● HATEOAS complements integration testing

Page 17: Rest

HATEOAS – Semantic Linking

● GET a single resource, it describes all actions that could be done on it.

curl -H “Accept: application/xml” http://host/cars/rabbit–<car> <make>VW</make> <model>Rabbit</model> <description>Entry-level hatchback...</description> <link rel=“trim” content-type=“application/xml” href=“http://host/cars/rabbit/trim”/> <link rel=“tech” content-type=“application/xml” href=“http://host/cars/rabbit/tech”/></car>

curl -H “Accept: application/xml” http://host/cars/rabbit–<car> <make>VW</make> <model>Rabbit</model> <description>Entry-level hatchback...</description> <link rel=“trim” content-type=“application/xml” href=“http://host/cars/rabbit/trim”/> <link rel=“tech” content-type=“application/xml” href=“http://host/cars/rabbit/tech”/></car>

Page 18: Rest

HATEOAS – Semantic Linking (for Humans)

● GET a single resource, it draw links to all actions on single page.

curl -H “Accept: text/html” http://host/cars/rabbit–<html> <title>Rabbit</title> <body> <h1>Rabbit</h1>

<dl> <dt>Make</dt><dd>VW</dd> <dt>Model</dt><dd>Rabbit</dd> <dt>Description</dt><dd>Entry-level hatchback...</dd></dl><p><a rel=“trim” href=“http://host/cars/rabbit/trim”>Trim</a></p><p><a rel=“tech” href=“http://host/cars/rabbit/tech”>Tech</a></p>

</body></html>

curl -H “Accept: text/html” http://host/cars/rabbit–<html> <title>Rabbit</title> <body> <h1>Rabbit</h1>

<dl> <dt>Make</dt><dd>VW</dd> <dt>Model</dt><dd>Rabbit</dd> <dt>Description</dt><dd>Entry-level hatchback...</dd></dl><p><a rel=“trim” href=“http://host/cars/rabbit/trim”>Trim</a></p><p><a rel=“tech” href=“http://host/cars/rabbit/tech”>Tech</a></p>

</body></html>

Page 19: Rest

HTTP – Uniform Interface

REST often uses HTTP. We all really like HTTP because it is:● Stateless● Scalable● Cachable● Proxieable● We already use it and have tons of

infrastructure to support it.

Page 20: Rest

HTTP – Uniform Interface

REST often uses HTTP. We all really like HTTP because it is:● Stateless● Scalable● Cachable● Proxieable● We already use it and have tons of

infrastructure to support it.

Page 21: Rest

HTTP Verbs (you've seen these)

Common HTTP Verb Table:

POST create /cars Create resource,post to collection

GET show /cars/1

PUT update /cars/1 Update new or existing resource*

DELETE destroy /cars/1

* REST sez... If I want to prescribe the identifer, I can PUT to the URI, regardless if the resource already exists.

Page 22: Rest

HTTP Verbs (some you might not have seen)

Common HTTP Verb Table:

POST create /cars Create resource,post to collection

GET show /cars/1

PUT update /cars/1 Update new or existing resource

DELETE destroy /cars/1

HEAD info /cars/1 Same as show, no body

OPTIONS options /cars/1 Server options

TRACE loop-back /cars/1 Loop-back of request, test chain of proxies

Less-familiar verbs (in Rails circles at least):

Page 23: Rest

HTTP Verbs

Common HTTP Verb Table:

POST create /cars Create resource,post to collection

GET show /cars/1

PUT update /cars/1 Update new or existing resource

DELETE destroy /cars/1

HEAD info /cars/1 Same as show, no body

OPTIONS options /cars/1 Server options

TRACE loop-back /cars/1 Loop-back of request, test chain of proxies

Less-familiar verbs (in Rails circles at least):

Page 24: Rest

HTTP Verbs “100 Continue”

HEAD /cars/11

Client

Page 25: Rest

HTTP Verbs “100 Continue”

HEAD /cars/11

100 ContinueClient Server2

Page 26: Rest

HTTP Verbs “100 Continue”

HEAD /cars/11

100 Continue

PUT /cars/1[ a bunch of data ]

3

Client Server2

Used when sending fles / multipart form / octet-streamSupported by Unicorn (Rainbows!)

Page 27: Rest

HTTP Response Status Codes

http://webmachine.basho.com/diagram.html

Rackanyone?

Page 28: Rest

Response Status Codes

● Fairly simple to test and usehttp://github.com/rack/rack/blob/master/lib/rack/utils.rb#L369

## application_controller.rb

def permission_denied render :text => “403 Forbidden”, :status => :forbiddenend

## features/forbidden.feature

Scenario: Forbidden page When I visit forbidden page Then I should be forbidden

## features/custom_steps.rb

Then /^I should be forbidden$/ do page.driver.response.status.should == 403end

## application_controller.rb

def permission_denied render :text => “403 Forbidden”, :status => :forbiddenend

## features/forbidden.feature

Scenario: Forbidden page When I visit forbidden page Then I should be forbidden

## features/custom_steps.rb

Then /^I should be forbidden$/ do page.driver.response.status.should == 403end

Page 29: Rest

Headers

● Great place for sending and receiving metadata including your own● X-My-Custom-Header “foo”

● Accept* headers● curl is your friend

curl -i -X GET \ -H "Accept: application/xml" \ -H “Accept-Language: es-US” \ http://server/resources/key

curl -i -X GET \ -H "Accept: application/xml" \ -H “Accept-Language: es-US” \ http://server/resources/key

Page 30: Rest

Caching with Etags

ClientClient ServerServer

GET /cars/rabbit

Page 31: Rest

Caching with Etags

ClientClient ServerServer

GET /cars/rabbit

HTTP/1.1 200 OKETag: 109h-402-f09h

Page 32: Rest

Caching with Etags

ClientClient ServerServer

GET /cars/rabbit

HTTP/1.1 200 OKETag: 1f09-402-f09h

GET /cars/rabbitIf-None-Match: “1f09-402-f09h”

HTTP/1.1 301 Not ModifiedETag: 1f09-402-f09hContent-Length: 0

Page 33: Rest

Security

● Mainly SSL● Stateless, send with each request● Slight deviation with sessions to make

human web apps more usable (and the bookmark case)

● Others, but not universal unless the can be adapted to use HTTP headers

Page 34: Rest

Protocol Buffers

http://code.google.com/p/protobuf/

● Google projects● Simple message format● Binary, but language agnostic● Enterprisey – And wicked fast!

Page 35: Rest

Meaningful Keys

● Rails, more specifcally AR, doesn't like not relying on auto-generated identifers

● Humans like identifers that are meaningful on their face

● Machines do to (primary index for free)● Ripple :key_on

Page 36: Rest

Rails and REST

● The Rails machinery tries to promote REST, but that doesn't mean that all Rails applications are RESTful

● Routing: resource, resources

## config/routes.rb

MyApp::Application.routes.draw do resources :cars do resource :engine endend

## config/routes.rb

MyApp::Application.routes.draw do resources :cars do resource :engine endend

Page 37: Rest

From Design to Code

● Identify which frst-class resource is being represented

● Turn verbs into nouns (roughly)E.g. If you want to “ship” some packages, consider creating a shipment resource that has_many packages.

● Creating a collection of objects, PUT to the parent using accepts-nested-attributes-for

● Rule of thumb – don't go more than 2 deep when nesting resources

Page 38: Rest

ANAF● Accepts-nested-attributes-for

● Thin out controller logic

● Useful pattern in Rails, felds_for helper

## config/routes.rbMyApp::Application.routes.draw do resources :manufacturers do resource :models endend

## app/models/manufacturer.rbclass Manufacturer has_many :models accepts_nested_attributes_for :modelsend

## app/views/manufacturers/show.html.haml- form_for @manufacturer do |f| - fields_for :models do |ff| = ff.text_field :name

## config/routes.rbMyApp::Application.routes.draw do resources :manufacturers do resource :models endend

## app/models/manufacturer.rbclass Manufacturer has_many :models accepts_nested_attributes_for :modelsend

## app/views/manufacturers/show.html.haml- form_for @manufacturer do |f| - fields_for :models do |ff| = ff.text_field :name

Page 39: Rest

Multi-step Form

Query parameters for view logic:

1. GET http://host/products/new

<h1>Select Category:</h1>

Page 40: Rest

Multi-step Form

Query parameters for view logic:

1. GET http://host/products/new

<h1>Select Category:</h1>

2. GET http://host/products/new?cat=laptops

<h1>Category: Laptops, Select Size:</h1>

Page 41: Rest

Multi-step Form

Query parameters for view logic:

1. GET http://host/products/new

<h1>Select Category:</h1>

2. GET http://host/products/new?cat=laptops

<h1>Category: Laptops, Select Size:</h1>

3. GET http://host/products/new?cat=laptops&size=17in

<h1>Category: Laptops, Size: 17in. Product Details:</h1>

Page 42: Rest

Multi-step Form

Query parameters for view logic:

1. GET http://host/products/new

<h1>Select Category:</h1>

2. GET http://host/products/new?cat=laptops

<h1>Category: Laptops, Select Size:</h1>

3. GET http://host/products/new?cat=laptops&size=17in

<h1>Category: Laptops, Size: 17in. Product Details:</h1>

4. POST http://host/products [form data]

Page 43: Rest

Inherited Resources● José Valim – Now part of Rails core. Also

wrote responders (part of Rails 3)● Convention over confguration, like Rails● Very DRY, thin controllers● Easy to override● Saves on controller unit tests

Page 44: Rest

Before and After IR

<code>

Page 45: Rest

IR Overriding Defaults

● Beginning of association chain● End of association chain● Build resource● Collections

<code>

● Responders (use i18n ./confg/locales/en.yaml to override fash messages)

Page 46: Rest

Vision of the Future

● Every presentation ought to have one

MM VV CC Model View Controller

Page 47: Rest

Vision of the Future

● Every presentation ought to have one

MM VV CC

MM RR ECEC+

Model View Controller

< becomes >

Model Resource + Enhanced Client

Page 48: Rest

Vision of the Future

● Every presentation ought to have one

*EC – Pending marketing review

MM VV CC

MM RR ECEC+

Model View Controller

< becomes >

Model Resource + Enhanced Client

Page 49: Rest

The Future is Now: Restfuliehttp://github.com/caelum/restfulie

● Manages Accept* headers better than Rails● Uses “tokamak” view fles to create proper

rel links.● Can be used along side of IR

<code>

Page 50: Rest

Thanks