Slide 1

Slide 1 text

DESIGNING HTTP INTERFACES AND RESTFUL WEB SERVICES

Slide 2

Slide 2 text

David Zuelke

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Slide 5

Slide 5 text

@dzuelke

Slide 6

Slide 6 text

THE OLDEN DAYS Before REST was En Vogue

Slide 7

Slide 7 text

http://www.acme.com/index.php?action=zomg&page=lol

Slide 8

Slide 8 text

along came

Slide 9

Slide 9 text

K dis is srs SEO

Slide 10

Slide 10 text

and said

Slide 11

Slide 11 text

NEIN NEIN NEIN NEIN DAS IST VERBOTEN

Slide 12

Slide 12 text

at least if they were

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

so we had to make URLs "SEO friendly"

Slide 15

Slide 15 text

http://www.acme.com/zomg/lol

Slide 16

Slide 16 text

and then things got out of control

Slide 17

Slide 17 text

because nobody really had a clue

Slide 18

Slide 18 text

http://acme.com/videos/latest/hamburgers

Slide 19

Slide 19 text

http://acme.com/search/lolcats/pictures/yes/1/200

Slide 20

Slide 20 text

oh dear…

Slide 21

Slide 21 text

THE RISE OF WEB SERVICES Ohai, I'm ur CEO, I canhaz SOAP API plz, today, kthx?

Slide 22

Slide 22 text

POST  /soapendpoint.php  HTTP/1.1   Host:  localhost   Content-­‐Type:  text/xml;  charset=utf-­‐8                                  123456                   HTTP/1.1  200  OK   Content-­‐Type:  text/xml;  charset=utf-­‐8                                                    123456                  Red  Stapler                  3.14                                

Slide 23

Slide 23 text

POST  /soapendpoint.php  HTTP/1.1   Host:  localhost   Content-­‐Type:  text/xml;  charset=utf-­‐8                                  987654                   HTTP/1.1  500  Internal  Service  Error   Content-­‐Type:  text/xml;  charset=utf-­‐8                                  SOAP-­‐ENV:Server              Unknown  Product                    

Slide 24

Slide 24 text

SOAP sucks, said everyone

Slide 25

Slide 25 text

let's build APIs without the clutter, they said

Slide 26

Slide 26 text

example: the old http://joind.in/ API

Slide 27

Slide 27 text

POST  /api/talk  HTTP/1.1   Host:  joind.in   Content-­‐Type:  text/xml;  charset=utf-­‐8                                                        Chuck  Norris                                  roundhousekick                                                                      42                     HTTP/1.1  200  OK   Content-­‐Type:  text/xml;  charset=utf-­‐8               My  Test  Talk       This  is  a  sample  talk  description       42      

Slide 28

Slide 28 text

PROBLEMS WITH THIS API • Always a POST • Doesn't use HTTP Authentication • Operation information is enclosed in the request ("getdetail") • Nothing there is cacheable • Everything through one endpoint (/api/talks for talks)

Slide 29

Slide 29 text

Level 0 in the Richardson Maturity Model: Plain old XML over the wire in an RPC fashion

Slide 30

Slide 30 text

Room for improvement: use one URI for each resource “ “

Slide 31

Slide 31 text

That would be Level 1 in Richardson's Maturity Model

Slide 32

Slide 32 text

Level 0 and Level 1 are a bag of hurt. Do not use them. Ever.

Slide 33

Slide 33 text

ALONG CAME ROY FIELDING And Gave Us REST

Slide 34

Slide 34 text

that was awesome

Slide 35

Slide 35 text

because everyone could say

Slide 36

Slide 36 text

J I haz REST nao

Slide 37

Slide 37 text

when in fact

Slide 38

Slide 38 text

they absolutely didn’t

Slide 39

Slide 39 text

REST What Does That Even Mean?

Slide 40

Slide 40 text

REpresentational State Transfer

Slide 41

Slide 41 text

Roy Thomas Fielding: Architectural styles and the design of network based software architectures.

Slide 42

Slide 42 text

• Client-Server • Stateless • Cacheable • Layered System • Code on Demand (optional) • Uniform Interface REST CONSTRAINTS

Slide 43

Slide 43 text

• A URL identifies a Resource • Methods perform operations on resources • The operation is implicit and not part of the URL • A hypermedia format is used to represent the data • Link relations are used to navigate a service UNIFORM INTERFACE

Slide 44

Slide 44 text

a web page is not a resource

Slide 45

Slide 45 text

it is a (complete) representation of a resource

Slide 46

Slide 46 text

GET  /products/  HTTP/1.1   Host:  acme.com   Accept:  application/json HTTP/1.1  200  OK
 Content-­‐Type:  application/json;  charset=utf-­‐8   Allow:  GET,  POST   [      {          id:  1234,          name:  "Red  Stapler",          price:  3.14,          location:  "http://acme.com/products/1234"      }   ] GETTING JSON BACK

Slide 47

Slide 47 text

GET  /products/  HTTP/1.1   Host:  acme.com   Accept:  application/xml HTTP/1.1  200  OK   Content-­‐Type:  application/xml;  charset=utf-­‐8   Allow:  GET,  POST                    Red  Stapler          3.14         GETTING XML BACK

Slide 48

Slide 48 text

but those are not hypermedia formats!

Slide 49

Slide 49 text

(more on that a bit later)

Slide 50

Slide 50 text

GET  /products/  HTTP/1.1   Host:  acme.com   Accept:  application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,*/*;q=0.5   User-­‐Agent:  Mozilla/5.0  (Macintosh;  U;  Intel  Mac  OS  X  10_5_8;  en-­‐us)  AppleWebKit… HTTP/1.1  200  OK   Content-­‐Type:  text/html;  charset=utf-­‐8   Allow:  GET,  POST                            ACME  Inc.  Products                      

Our  Incredible  Products

                  AND FINALLY, HTML

Slide 51

Slide 51 text

VOLUME ONE Designing an HTTP Interface

Slide 52

Slide 52 text

FIRST: DEFINE RESOURCES A Good Approach: Structure Your URLs

Slide 53

Slide 53 text

"BAD URLS" • http://www.acme.com/product/ • http://www.acme.com/product/filter/cats/desc • http://www.acme.com/product/1234 • http://www.acme.com/photos/product/1234 • http://www.acme.com/photos/product/1234/new • http://www.acme.com/photos/product/1234/5678 err...? photo or product ID? new what?

Slide 54

Slide 54 text

"GOOD URLS" • http://www.acme.com/products/ • http://www.acme.com/products/?filter=cats&sort=desc • http://www.acme.com/products/1234 • http://www.acme.com/products/1234/photos/ • http://www.acme.com/products/1234/photos/?sort=latest • http://www.acme.com/products/1234/photos/5678 a list of products filtering is a query a single product all photos

Slide 55

Slide 55 text

now here's the ironic part

Slide 56

Slide 56 text

URLs don't matter once you have a fully RESTful interface

Slide 57

Slide 57 text

but it’s helpful to think in terms of resources

Slide 58

Slide 58 text

SECOND: USE RESOURCES CRUD, but not really

Slide 59

Slide 59 text

COLLECTION OPERATIONS • http://www.acme.com/products/ • GET to retrieve a list of products • POST to create a new product • returns • 201 Created • Location: http://www.acme.com/products/1235

Slide 60

Slide 60 text

ITEM OPERATIONS • http://www.acme.com/products/1234 • GET to retrieve • PUT to update • DELETE to, you guessed it, delete

Slide 61

Slide 61 text

Now we are at Level 2 in RMM

Slide 62

Slide 62 text

RMM LEVEL 2 • Use HTTP verbs • GET (safe and idempotent) • POST (unsafe, not idempotent) • PUT & DELETE (unsafe, idempotent) • Use HTTP status codes to indicate result success • e.g. HTTP/1.1 409 Conflict

Slide 63

Slide 63 text

THE TWITTER (V1) API Not RESTful, And Not Even Getting HTTP Right :(

Slide 64

Slide 64 text

mind you we're not even inspecting the RESTfulness

Slide 65

Slide 65 text

we're just looking at Twitter's API from an HTTP perspective

Slide 66

Slide 66 text

CURRENT STATE • GET http://api.twitter.com/1/statuses/show/12345.json • POST http://api.twitter.com/1/statuses/update.json • DELETE http://api.twitter.com/1/statuses/destroy/12345.json • GET http://api.twitter.com/1/statuses/retweets/12345.json • PUT http://api.twitter.com/1/statuses/retweet/12345.json Doesn’t allow Accept header Why a PUT? Why the difference? Posts to auth’d user! “DELETE destroy”, RPC much?

Slide 67

Slide 67 text

COULD BE SO MUCH SIMPLER • http://twitter.com/username/statuses/ • POST to create a new tweet • http://twitter.com/username/statuses/12345 • DELETE deletes (PUT could be used for updates) • http://twitter.com/username/statuses/12345/retweets/ • POST creates a new retweet

Slide 68

Slide 68 text

INTERMISSION What's the Biggest Reason for the Success of the Web?

Slide 69

Slide 69 text

WWW

Slide 70

Slide 70 text

first information exchange system

Slide 71

Slide 71 text

planetary scale

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

why is that possible?

Slide 75

Slide 75 text

Hyperlinks!

Slide 76

Slide 76 text

no tight coupling!

Slide 77

Slide 77 text

loosely coupled by design

Slide 78

Slide 78 text

no notification infrastructure

Slide 79

Slide 79 text

HTTP/1.1 404 Not Found

Slide 80

Slide 80 text

embraces failure

Slide 81

Slide 81 text

more information != more friction

Slide 82

Slide 82 text

no limits to scalability

Slide 83

Slide 83 text

WWW is protocol-centric

Slide 84

Slide 84 text

VOLUME TWO RESTful Services with Hypermedia

Slide 85

Slide 85 text

THE UNIFORM INTERFACE • Identification of Resources (e.g. through URIs) • Representations are conceptually separate! • Manipulation Through Representations (i.e. they are complete) • Self-Descriptive Messages (containing all information) • Hypermedia As The Engine Of Application State ("HATEOAS") "without you I am nothing"

Slide 86

Slide 86 text

HATEOAS The Missing Piece in the Puzzle

Slide 87

Slide 87 text

ONE LAST PIECE IS MISSING • How does a client know what to do with representations? • How do you go to the “next” operation? • What are the URLs for creating subordinate resources? • Where is the contract for the service?

Slide 88

Slide 88 text

HYPERMEDIA AS THE ENGINE OF APPLICATION STATE • Use links to allow clients to discover locations and operations • Link relations are used to express the possible options • Clients do not need to know URLs, so they can change • The entire application workflow is abstracted, thus changeable • The hypermedia type itself could be versioned if necessary • No breaking of clients if the implementation is updated!

Slide 89

Slide 89 text

(X)HTML and Atom are Hypermedia formats

Slide 90

Slide 90 text

Or you roll your own...

Slide 91

Slide 91 text

GET  /products/1234  HTTP/1.1   Host:  acme.com   Accept:  application/vnd.com.acme.shop+xml HTTP/1.1  200  OK   Content-­‐Type:  application/vnd.come.acme.shop+xml;  charset=utf-­‐8   Allow:  GET,  PUT,  DELETE          1234      Red  Stapler      3.14
       re-use Atom for
 link relations meaning defined in IANA Link Relations list A CUSTOM MEDIA TYPE Remind clients of Uniform Interface :)

Slide 92

Slide 92 text

boom, RMM Level 3

Slide 93

Slide 93 text

XML is really good for hypermedia formats

Slide 94

Slide 94 text

(hyperlinks, namespaced attributes, re-use of formats, …)

Slide 95

Slide 95 text

JSON is more difficult

Slide 96

Slide 96 text

(no hyperlinks, no namespaces, no element attributes)

Slide 97

Slide 97 text

       1234      Red  Stapler            3.14
 {      id:  1234,      name:  "Red  Stapler",      links:  [          {              rel:  "payment",              type:  "application/vnd.com.acme.shop+json",              href:  "http://acme.com/products/1234/payment"          }      ],      price:  3.14   } XML VERSUS JSON

Slide 98

Slide 98 text

       1234      Red  Stapler            3.14
 {      id:  1234,      name:  "Red  Stapler",      links:  [          {              rel:  "payment",              type:  "application/vnd.com.acme.shop+json",              href:  "http://acme.com/products/1234/payment"          }      ],      price:  {          amount:  3.14,          currency:  "EUR"      }   } XML VERSUS JSON Content (“node value”) still the same Float becomes object, stuff breaks

Slide 99

Slide 99 text

JSON is difficult to evolve without breaking clients

Slide 100

Slide 100 text

XML’s document model is built for extensibility

Slide 101

Slide 101 text

                 Bacon          5.99          

Slide 102

Slide 102 text

                 Bacon          5.99          OMNOMNOM  Bacon          

Slide 103

Slide 103 text

                 Bacon          5.99          

Slide 104

Slide 104 text

                 Bacon          5.99          4.49          

Slide 105

Slide 105 text

                 Bacon          Speck          5.99          4.49        

Slide 106

Slide 106 text

                 Bacon          Speck          5.99                  

Slide 107

Slide 107 text

and hey

Slide 108

Slide 108 text

without Hypermedia, your HTTP interface is not RESTful

Slide 109

Slide 109 text

that’s totally fine
 and sometimes even the only way to do it

Slide 110

Slide 110 text

(e.g. CouchDB or S3 are never going to be RESTful)

Slide 111

Slide 111 text

just avoid calling it a "REST API" :)

Slide 112

Slide 112 text

$next  =  'http://shop.com/search?q=sharks';
 while($next)  {
        $doc  =  DOMDocument::loadXML(file_get_contents($url));
        $xpath  =  new  DOMXPath($doc);
        foreach($xpath-­‐>query('/searchResult/product')  as  $product)  {
                MyMagicDatabase::import($product);
        }
        $next  =  $xpath-­‐>evaluate('/searchResult/link[@rel="next"]/@href');
 } WITH HATEOAS, CLIENTS BECOME STATE MACHINES                              ...          ...          ...  

Slide 113

Slide 113 text

good Hypermedia format example: the Lovefilm API

Slide 114

Slide 114 text

       6      1      1                                  true          2003-­‐09-­‐12                    <id>http://openapi.lovefilm.com/catalog/title/59643</id>          <adult>false</adult>          <number_of_ratings>574</number_of_ratings>          <rating>4</rating>          <category  scheme="http://openapi.lovefilm.com/categories/catalog"  term="games"/>          <category  scheme="http://openapi.lovefilm.com/categories/format"  term="Xbox"/>          <category  scheme="http://openapi.lovefilm.com/categories/genres"  term="Adventure"/>          <category  scheme="http://openapi.lovefilm.com/categories/genres"  term="Role-­‐playing"/>          <category  scheme="http://openapi.lovefilm.com/categories/certificates/bbfc"  term="TBC"/>          <link  href="http://openapi.lovefilm.com/catalog/title/59643/synopsis"                      rel="http://schemas.lovefilm.com/synopsis"  title="synopsis"/>          <link  href="http://openapi.lovefilm.com/catalog/title/59643/reviews"                      rel="http://schemas.lovefilm.com/reviews"  title="reviews"/>          <link  href="http://www.lovefilm.com/product/59643-­‐Star-­‐Wars-­‐Knights-­‐of-­‐the-­‐Old-­‐Republic.html?cid=LFAPI"                      rel="alternate"  title="web  page"/>      </catalog_title>   </search>

Slide 115

Slide 115 text

ROOM FOR IMPROVEMENT IN THE LOVEFILM API • Uses application/xml instead of a custom media type • Once that is fixed, all the link elements could also have a “type” attribute indicating the media type • Should use XML namespaces on the root element, with one namespace per type (e.g. “urn:com.lovefilm.api.item”, “urn:com.lovefilm.api.searchresult” and so on) • That way, clients can determine the resource type easily

Slide 116

Slide 116 text

another great RESTful API: Huddle

Slide 117

Slide 117 text

                                                                                                                                                                       19475            98      2007-­‐10-­‐10T09:02:17Z      2011-­‐10-­‐10T09:02:17Z      Complete      9  

Slide 118

Slide 118 text

ROOM FOR IMPROVEMENT IN THE HUDDLE API • Uses custom rels like “thumb” or “avatar” not defined in the IANA registry (http://www.iana.org/assignments/link-relations) • Risk of collisions and ambiguity; should use something like “http://rels.huddle.net/thumb” instead. • Uses one global XML schema and namespace for all entities • Clients cannot detect entity type based on namespace • Difficult to evolve schema versions independently

Slide 119

Slide 119 text

API VERSIONING Media Types To The Rescue!

Slide 120

Slide 120 text

why not api.myservice.com/v1/foo/bar? and then api.myservice.com/v2/foo/bar?

Slide 121

Slide 121 text

different URLs means different resources!

Slide 122

Slide 122 text

also, keep bookmarks (by machines) in mind

Slide 123

Slide 123 text

GET  /products/1234  HTTP/1.1   Host:  acme.com   Accept:  application/vnd.com.myservice+xml HTTP/1.1  200  OK   Content-­‐Type:  application/vnd.com.myservice+xml;  charset=utf-­‐8   Allow:  GET,  PUT,  DELETE          Red  Stapler      3.14   API VERSION 1

Slide 124

Slide 124 text

(item sells out...)

Slide 125

Slide 125 text

GET  /products/1234  HTTP/1.1   Host:  acme.com   Accept:  application/vnd.com.myservice+xml HTTP/1.1  410  Gone   Content-­‐Type:  application/vnd.com.myservice+xml;  charset=utf-­‐8 API VERSION 1

Slide 126

Slide 126 text

API now offers a new protocol version with availability indicators (breaking change!)

Slide 127

Slide 127 text

GET  /products/1234  HTTP/1.1   Host:  acme.com   Accept:  application/vnd.com.myservice.v2+xml HTTP/1.1  200  OK   Content-­‐Type:  application/vnd.com.myservice.v2+xml;  charset=utf-­‐8   Allow:  GET,  PUT,  DELETE          Red  Stapler      3.14      false   API VERSION 2

Slide 128

Slide 128 text

clients can’t upgrade protocol for known URLs!

Slide 129

Slide 129 text

Also, imagine every install of phpBB or Drupal had an API

Slide 130

Slide 130 text

If the version is in the URL, clients need to regex those

Slide 131

Slide 131 text

http://sharksforum.org/community/api/v1/threads/102152

Slide 132

Slide 132 text

http://forum.sharksforum.org/api/v1/threads/102152

Slide 133

Slide 133 text

that would be fail

Slide 134

Slide 134 text

or what if another forum software wants the same API?

Slide 135

Slide 135 text

also would have to use “/v1/” in their URLs

Slide 136

Slide 136 text

URI based versioning kills interoperability

Slide 137

Slide 137 text

YOU MIGHT BE WONDERING Why Exactly Is This Awesome?

Slide 138

Slide 138 text

THE MERITS OF REST • Easy to evolve: add new features or elements without breaking BC • Easy to learn: developers can "browse" service via link rels • Easy to scale up: grows well with number of features, users and servers • Easy to implement: build it on top of HTTP, and profit! • Authentication & TLS • Caching & Load Balancing • Conditional Requests • Content Negotiation

Slide 139

Slide 139 text

but...

Slide 140

Slide 140 text

hold on, you say

Slide 141

Slide 141 text

a plain HTTP-loving service does the job, you say

Slide 142

Slide 142 text

surely, there is a merit to REST beyond extensibility, you ask

Slide 143

Slide 143 text

nope

Slide 144

Slide 144 text

"REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution. Many of the constraints are directly opposed to short-term efficiency. Unfortunately, people are fairly good at short-term design, and usually awful at long-term design." Roy Fielding

Slide 145

Slide 145 text

"Most of REST's constraints are focused on preserving independent evolvability over time, which is only measurable on the scale of years. Most developers simply don't care what happens to their product years after it is deployed, or at least they expect to be around to rewrite it when such change occurs." Roy Fielding

Slide 146

Slide 146 text

FURTHER READING • Leonard Richardson, Mike Amundsen, Sam Ruby
 RESTful Web APIs
 ISBN: 978-1449358068 • Jim Webber, Savas Parastatidis & Ian Robinson
 How to GET a Cup of Coffee
 http://www.infoq.com/articles/webber-rest-workflow • Roy Thomas Fielding
 Architectural Styles and the Design of Network-based Software Architectures
 http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

Slide 147

Slide 147 text

MORE BOOKS ON REST • Jim Webber, Savas Parastatidis, Ian Robinson
 REST in Practice
 ISBN: 978-0596805821 • Subbu Allamaraju
 RESTful Web Services Cookbook
 ISBN: 978-0596801687 • Leonard Richardson, Sam Ruby
 RESTful Web Services
 ISBN: 978-0596529260

Slide 148

Slide 148 text

The End

Slide 149

Slide 149 text

RESTFUL WEB SERVICES Thanks for listening! Contact: @dzuelke & [email protected]. rate my talk on joind.in!