Slide 1

Slide 1 text

REST for Web Developers Leeds PHP User Group, February 2013

Slide 2

Slide 2 text

What is REST? REpresentational State Transfer • Resources • Collections

Slide 3

Slide 3 text

Pretty URLs • http://api.example.com/articles • http://api.example.com/articles/2756 • http://api.example.com/articles/2756/comments • http://api.example.com/comments/101134

Slide 4

Slide 4 text

REST and HTTP On the web, we use HTTP's features to implement REST • Verbs • Status codes • Headers

Slide 5

Slide 5 text

Verbs

Slide 6

Slide 6 text

Verbs Verbs give us CRUD Verb Collection Resource GET fetch resources fetch one resource POST create resource PUT [create]/update resource DELETE delete resource

Slide 7

Slide 7 text

Status Codes

Slide 8

Slide 8 text

Common Status Codes 200 OK 201 Created 204 No Content 304 Not Modified 400 Bad Request 404 Not Found

Slide 9

Slide 9 text

Headers

Slide 10

Slide 10 text

Request Headers > GET / HTTP/1.1 > User-Agent: curl/7.27.0 > Host: www.lornajane.net > Accept: */* (examples made by cURL http://curl.haxx.se/)

Slide 11

Slide 11 text

Response Headers < HTTP/1.1 200 OK < Server: Apache/2.2.22 (Ubuntu) < X-Powered-By: PHP/5.4.6-1ubuntu1.1 < X-Pingback: http://www.lornajane.net/xmlrpc.php < Vary: Accept-Encoding < Content-Type: text/html; charset=UTF-8 < Transfer-Encoding: chunked < Date: Wed, 06 Feb 2013 14:02:25 GMT < X-Varnish: 179948671 179948601 < Age: 18 < Via: 1.1 varnish < Connection: keep-alive

Slide 12

Slide 12 text

Content Negotiation Agree on a format using the Accept and Content-Type headers Header from Chrome: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 • Server works out what format to send back • Changing Accept header changes response format

Slide 13

Slide 13 text

Parsing Accept Headers Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Format Weighting text/html 100% application/xhtml+xml 100% application/xml 90% */* 80%

Slide 14

Slide 14 text

Negotiating Other Content Details We also have: • Accept-Language • Accept-Encoding • Accept-Charset

Slide 15

Slide 15 text

Is Anyone Tired of Theory Yet?

Slide 16

Slide 16 text

REST in Practice

Slide 17

Slide 17 text

GET Request Headers GET https://api.github.com/repos/lornajane/demo/issues > GET /repos/lornajane/demo/issues HTTP/1.1 > User-Agent: curl/7.27.0 > Host: api.github.com > Accept: */* > Authorization: token 2d2d0a9b70d86b3b3ed9bac915b47a4d29fcf556f

Slide 18

Slide 18 text

GET Response Headers GET https://api.github.com/repos/lornajane/demo/issues < HTTP/1.1 200 OK < Server: GitHub.com < Date: Sun, 17 Feb 2013 20:32:24 GMT < Content-Type: application/json; charset=utf-8 < Status: 200 OK < Vary: Accept, Authorization, Cookie < Cache-Control: private, max-age=60, s-maxage=60 < Last-Modified: Sun, 17 Feb 2013 20:19:19 GMT < ETag: "d30cd8e8cd3f86e71c40334ed104f345" < X-OAuth-Scopes: gist, repo < X-Accepted-OAuth-Scopes: repo, public_repo < X-GitHub-Media-Type: github.beta < Content-Length: 1953

Slide 19

Slide 19 text

GET Response Body GET https://api.github.com/repos/lornajane/demo/issues { "url": "https://api.github.com/repos/lornajane/demo/issues/1", "comments_url": "https://api.github.com/repos/lornajane/demo/issues/1/c "html_url": "https://github.com/lornajane/demo/issues/1", "number": 1, "title": "It's Broken", "user": { ... }, "state": "open", "comments": 0, "created_at": "2013-02-17T20:19:19Z", "updated_at": "2013-02-17T20:19:19Z", "body": "This Thing Does Not Work" }

Slide 20

Slide 20 text

Hypermedia Hypermedia are hyperlinks for APIs • Clients can find related data • Relying on following links means URLs can change

Slide 21

Slide 21 text

POST Request POST https://.../repos/lornajane/demo/issues/1/comments > POST /repos/lornajane/demo/issues/1/comments HTTP/1.1 > User-Agent: curl/7.27.0 > Host: api.github.com > Accept: */* > Content-Type: application/json > Authorization: token 2d2d0a9b70d86b3b3ed9bac915b47a4d29fcf556f > Content-Length: 37 > {"body": "some comment on the issue"}

Slide 22

Slide 22 text

POST Response Header POST https://.../repos/lornajane/demo/issues/1/comments < HTTP/1.1 201 Created < Server: GitHub.com < Date: Sun, 17 Feb 2013 21:27:15 GMT < Content-Type: application/json; charset=utf-8 < Status: 201 Created < Location: https://.../repos/lornajane/demo/issues/comments/13697012 < Content-Length: 1400 < ETag: "f8661566f14902412153409d034d464b" < Cache-Control: max-age=0, private, must-revalidate

Slide 23

Slide 23 text

POST Response Body POST https://.../repos/lornajane/demo/issues/1/comments { "url": "https://.../repos/lornajane/demo/issues/comments/13697012", "issue_url": "https://.../repos/lornajane/demo/issues/11093693", "id": 13697012, "user": { ... }, "created_at": "2013-02-17T21:27:15Z", "updated_at": "2013-02-17T21:27:15Z", "body": "some comment on the issue" }

Slide 24

Slide 24 text

PUT Request PUT https://.../repos/lornajane/demo/issues/comments/13697012 > PUT /repos/lornajane/demo/issues/comments/13697012 HTTP/1.1 > User-Agent: curl/7.27.0 > Host: api.github.com > Accept: */* > Content-Type: application/json > Authorization: token 2d2d0a9b70d86b3b3ed9bac915b47a4d29fcf556f < Content-Length: 1403 {amended json data block}

Slide 25

Slide 25 text

PUT Response PUT https://.../repos/lornajane/demo/issues/comments/13697012 < HTTP/1.1 200 OK < Server: GitHub.com < Date: Sun, 17 Feb 2013 22:09:14 GMT < Content-Type: application/json; charset=utf-8 < Connection: keep-alive < Status: 200 OK < X-OAuth-Scopes: gist, repo < X-Accepted-OAuth-Scopes: repo, public_repo < Content-Length: 1403 < ETag: "eccb456c8339572840f4c51dd8180fc7" < Cache-Control: max-age=0, private, must-revalidate

Slide 26

Slide 26 text

... except GitHub use PATCH

Slide 27

Slide 27 text

PATCH Request PATCH https://.../repos/lornajane/demo/issues/comments/13697012 > PATCH /repos/lornajane/demo/issues/comments/13697012 HTTP/1.1 > User-Agent: curl/7.27.0 > Host: api.github.com > Accept: */* > Content-Type: application/json > Authorization: token 2d2d0a9b70d86b3b3ed9bac915b47a4d29fcf556f < Content-Length: 39 {"body":"some other, improved comment"}

Slide 28

Slide 28 text

PATCH Response PATCH https://.../repos/lornajane/demo/issues/comments/13697012 < HTTP/1.1 200 OK < Server: GitHub.com < Date: Sun, 17 Feb 2013 22:09:14 GMT < Content-Type: application/json; charset=utf-8 < Connection: keep-alive < Status: 200 OK < X-OAuth-Scopes: gist, repo < X-Accepted-OAuth-Scopes: repo, public_repo < Content-Length: 1403 < ETag: "eccb456c8339572840f4c51dd8180fc7" < Cache-Control: max-age=0, private, must-revalidate

Slide 29

Slide 29 text

DELETE Request DELETE https://.../repos/lornajane/demo/issues/comments/13697012 > DELETE /repos/lornajane/demo/issues/comments/13697012 HTTP/1.1 > User-Agent: curl/7.27.0 > Host: api.github.com > Accept: */* > Authorization: token 2d2d0a9b70d86b3b3ed9bac915b47a4d29fcf556f

Slide 30

Slide 30 text

DELETE Response DELETE https://.../repos/lornajane/demo/issues/comments/13697012 < HTTP/1.1 204 No Content < Server: GitHub.com < Date: Sun, 17 Feb 2013 22:22:37 GMT < Connection: keep-alive < Status: 204 No Content < X-RateLimit-Limit: 5000 < X-RateLimit-Remaining: 4967 < X-OAuth-Scopes: gist, repo < X-Accepted-OAuth-Scopes: repo, public_repo < X-GitHub-Media-Type: github.beta < X-Content-Type-Options: nosniff

Slide 31

Slide 31 text

HTTP Superpowers

Slide 32

Slide 32 text

Authorization Headers • Options for auth: Basic/Digest, OAuth • Use headers, this information isn't part of a resource • Use tokens and expire tokens

Slide 33

Slide 33 text

30-Second OAuth Overview OAuth handles the relationship between: • a user • their data stored on a provder • a consumer wanting to access their data Use tokens for access, these can be revoked/expired

Slide 34

Slide 34 text

Caching Headers Used exactly as we do on the web! • Expires to say how long the client should keep the content • ETag or Last-Modified to check if something has changed • These can be used to check that a PUT updates the expected resource version

Slide 35

Slide 35 text

RESTful Services

Slide 36

Slide 36 text

When to use REST • For data-driven APIs • Where REST is (or can be) understood

Slide 37

Slide 37 text

Designing RESTful Services • Resources, verbs and headers • Consider the failure case • How much data to return? How little? • Split into subresources • Allow more/less verbose representations

Slide 38

Slide 38 text

Any Questions?

Slide 39

Slide 39 text

Thanks • http://www.lornajane.net/ • @lornajane