Upgrade to Pro — share decks privately, control downloads, hide ads and more …

REST for Web Developers

REST for Web Developers

DrupalCon Portland session on REST, what it should look like, how to use it, and how to make the best of it in your own applications

Lorna Mitchell

May 22, 2013
Tweet

More Decks by Lorna Mitchell

Other Decks in Technology

Transcript

  1. URLs are Pretty AND Hackable • http://api.example.com/articles • http://api.example.com/articles/2756 •

    http://api.example.com/articles/2756/comments • http://api.example.com/comments/101134
  2. Using REST With HTTP On the web, we use HTTP's

    features to implement REST • Verbs • Status codes • Headers
  3. Verbs Give Us CRUD CRUD: Create, Read, Update, Delete Verb

    Collection Resource GET fetch resources fetch one resource POST create resource PUT [create]/update resource DELETE delete resource
  4. Common Status Codes 200 OK 201 Created 204 No Content

    304 Not Modified 400 Bad Request 404 Not Found
  5. 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/)
  6. 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
  7. Negotiating Content Format 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
  8. 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
  9. 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
  10. 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" }
  11. Hypermedia are Hyperlinks for APIs • Clients can find related

    data • Relying on following links means URLs can change
  12. 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"}
  13. 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
  14. 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" }
  15. 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}
  16. 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
  17. 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"}
  18. 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
  19. 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
  20. 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
  21. Authorization Headers • Options for auth: Basic/Digest, OAuth • Use

    headers, this information isn't part of a resource • Use tokens and expire tokens
  22. 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
  23. 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
  24. 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