doing rest right
DESCRIPTION
Presentation for BT Developer Day, 9 March 2010.TRANSCRIPT
How to do RESTful web services right
Kerry Buckley & Paul Moser
BT DevCon2
9 March 2010
How to do RESTful web services right
One way
How to do RESTful web services right
(for some value of ‘right’)
One way
What is REST?
REST is an architectural style, not a protocol or a standard. Hence many values of “right” (and much disagreement).
‘A style of software architecture for
distributed hypermedia systems such as the World Wide Web’
Not necessarily HTTP, although in practice it generally is.
Not SOAP
Seems to be a common (but wrong) definition.
Constraints
• Client-server
• Stateless
• Cacheable
• Layered system
• Uniform interface
Principles
• Identification of resources
• Manipulation of resources through these representations
• Self-descriptive messages
• Hypermedia as the engine of application state
Goals
• Scalability of component interactions
• Generality of interfaces
• Independent deployment of components
• Intermediary components to reduce latency, enforce security and encapsulate legacy systems
Shop example
• List products
• View a product
• Create an order for a number of products
• Cancel order
• Pay for order
XML-RPC(URI-tunnelling)
GET /api?action=list_products
GET /api?action=view_product&product_id=123
GET /api?action=create_order&product_id=123&product_id=456…
GET/api?action=pay_order&order_id=42&card_number=1234…
Sometimes only a single ‘endpoint’ URI
GET /list_products
GET /view_product?product_id=123
GET /create_order?product_id=123&product_id=456…
GET/pay_order?order_id=42&card_number=1234…
Or one endpoint per method
GET /list_products
GET /view_product?product_id=123
POST /create_order?product_id=123&product_id=456…
POST /pay_order?order_id=42&card_number=1234…
Marginally better without unsafe GETs
POST /pay_order?order_id=42&card_number=1234…
def pay_order(order_id, card_number) { …}
Request maps onto method call.
✓Easy to understand
✓Works well for simple procedure calls
✓Simple to implement
✓Interoperable
✗Brittle
✗Tightly coupled
✗Failure cases require manual handling
✗No metadata
Need to know all the URIs, methods and parameters in advance (out-of-band documentation)
✗ Identification of resources
✗ Manipulation of resources through these representations
✗ Self-descriptive messages
✗ Hypermedia as the engine of application state
But is it REST?
POX(plain old XML)
Request
POST /create_order
<create_order_request> <line> <product_id>123</product_line> <quantity>1</quantity> </line> …</create_order_request>
Response
200 OK
<create_order_response> <status>OK</status> <order_id>42</order_id></create_order_response>
Both request and response have XML bodies.
✓Simple to implement
✓Interoperable
✓Allows complex data structures
✗Tightly coupled
✗No metadata
✗Doesn’t use web for robustness
✗Doesn’t use SOAP for robustness either
✗ Identification of resources
✗ Manipulation of resources through these representations
✗ Self-descriptive messages
✗ Hypermedia as the engine of application state
But is it REST?
CRUD
GET /products
GET /products/123
POST /orders
PUT /orders/42
DELETE /orders/42
POST /orders/42/payment
Representations• Hypermedia
- XHTML
- Atom
- Custom XML schema
• Non-hypermedia
- Generic XML
- YAML
- JSON
- CSV
- etc
✓Makes good use of HTTP
✓Uniform interface
✓Good for database-style applications
Because each resource has a URI you can use caching etc. Uniform interface: verbs are GET, POST, PUT and DELETE.
✗ Ignores hypermedia
✗Tight coupling through URI templates
✗Not self-describing
✓ Identification of resources
✓Manipulation of resources through these representations
✗ Self-descriptive messages
✗ Hypermedia as the engine of application state
But is it REST?
REST
API rootRequest
GET /
API rootResponse
200 OKContent-Type: application/vnd.rest-example.store+xml
<store> <link method="get" rel="products" href="http://rest-demo.local/products"/> <link method="get" rel="orders" href="http://rest-demo.local/orders"/></store>
Links contain information on what we can do.
View productsRequest
Get /products
Following the link with a relation of ‘products’ (link rel="products").
View productsResponse
200 OKContent-Type: application/vnd.rest-example.products+xml
<products> <link method="get" rel="latest" href="http://rest-demo.local/products"/> <product> <link method="get" rel="view" href="http://rest-demo.local/products/1"/> <code>A-001</code> <description>Tartan Paint</description> <price>4.95</price> </product> …</products>
Note link to retrieve the latest version of this resource (eg if you had it cached).
View ordersRequest
Get /orders
View ordersResponse
200 OKContent-Type: application/vnd.rest-example.orders+xml
<orders> <link method="get" rel="latest" href="http://rest-demo.local/orders"/> <link type="application/vnd.rest-example.order+xml" method="post" rel="new" href="http://rest-demo.local/orders"/></orders>
No orders yet, but note link to create a new one.
Place orderRequest
POST /ordersContent-Type: application/vnd.rest-example.order+xml
<order> <line> <product>http://rest-demo.local/products/1</product> <quantity>2</quantity> </line></order>
Again following a link, this time posting data of the specified type.
Place orderResponse
201 CreatedContent-Type: application/vnd.rest-example.order+xml
<order> <link method="get" rel="latest" href="http://rest-demo.local/orders/9"/> <link method="delete" rel="cancel" href="http://rest-demo.local/orders/9"/> <link type="application/vnd.rest-example.payment-details+xml" method="post" rel="pay" href="http://rest-demo.local/orders/9/pay"/> <line> <product>http://rest-demo.local/products/1</product> <quantity>2</quantity> <cost>9.90</cost> </line> <total>9.90</total></order>
Note links to cancel or pay for the order – HATEOAS! The links included would depend on the allowable state transitions (eg no cancel link for a despatched order).
Clients only need know
• The root URI (‘home page’) of the API
• Definitions for the media types used
- eg schemas or example documents
• Everything else is just HTTP and links
✓Makes full use of HTTP
✓Self-describing
✓Loosely coupled
Only need to know entry URI and media types – API can be explored using links. If link URIs change, well-behaved clients should not break.
✗More complex to implement
✗Transition links can lead back to RPC-style
Frameworks help. Tempting to just add a bunch of actions as links, using overloaded post.
✓ Identification of resources
✓ Manipulation of resources through these representations
✓ Self-descriptive messages
✓ Hypermedia as the engine of application state
But is it REST?
This is not the One True Way
As mentioned before, REST is just an architectural style. There are other approaches to creating RESTful APIs.
An alternative:‘Web site is your API’
• No separation between web site and API
• Representations are HTML
• Data submitted using HTML forms
• Semantics via microformats
Using HTTP features
Response codes• 200 OK
• 201 Created
• 202 Accepted
• 204 No content
• 301 Moved permanently
• 400 Bad request
• 403 Forbidden
• 404 Not found
• 405 Method not allowed
• 409 Conflict
• 410 Gone
• etc
Restricting transitions
Request Response
OPTIONS /orders/123(an open order)
200 OKAllow: GET, PUT, DELETE
OPTIONS /orders/42(a despatched order)
200 OKAllow: GET
Restricting transitions
Request Response
DELETE /orders/123Expect: 100-Continue
100 Continue
DELETE /orders/42Expect: 100-Continue
417 Expectation Failed
Prevent race conditions
Request
PUT /orders/123If-Unmodified-Since: Tue, 9 Mar 2010 11:00:00 GMT
Response
200 OK
or
412 Precondition Failed
Prevent race conditions
Request
GET /orders/123
Response (partial)
200 OKETag: 686897696a7c876b7e
Request
PUT /orders/123If-Match: 686897696a7c876b7e
Security
• HTTP basic
• HTTP digest
• Shared secret (OAuth etc)
• SSL
• Selective encryption
More
• Jim Webber tutorial
http://tinyurl.com/rest-tutorial
• Restfulie framework (Rails & Java):
http://tinyurl.com/restfulie