API Design: it's not rocket surgery (PHPNW2012)

15c49bd9f73317bf66952b9ee17414ef?s=47 Dave Ingram
October 06, 2012

API Design: it's not rocket surgery (PHPNW2012)

A slightly-updated version of my API design talk, compressed into 20 minutes for the PHPNW2012 unconference.

15c49bd9f73317bf66952b9ee17414ef?s=128

Dave Ingram

October 06, 2012
Tweet

Transcript

  1. API design It’s Not Rocket Surgery Dave Ingram @dmi October

    6, 2012
  2. Who am I? • Coder and Release Manager at GroupSpaces

    • Worked there for over 41/2 years • Twitter: @dmi • Github: dingram • Way too many projects of my own • Also involved in open source, including Phabricator • Occasionally found at London Hackspace
  3. Feedback/thoughts on Twitter: #apirocketsurgery (or @dmi)

  4. What this isn’t

  5. T T REST REST REST REST REST REST REST EST

    EST ST ST ST T T REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST RES RES REST REST REST REST REST REST REST REST REST REST REST REST REST R R R RE RE RE RES RES REST R
  6. T T REST REST REST REST REST REST REST EST

    EST ST ST ST T T REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST RES RES REST REST REST REST REST REST REST REST REST REST REST REST REST R R R RE RE RE RES RES REST R
  7. T T REST REST REST REST REST REST REST EST

    EST ST ST ST T T REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST REST R REST REST REST REST REST REST REST REST REST REST REST REST REST REST RES RES REST REST REST REST REST REST REST REST REST REST REST REST REST R R R RE RE RE RES RES REST R
  8. There’s so much more!

  9. URLs

  10. URLs verbs

  11. URLs verbs headers

  12. URLs verbs headers authentication

  13. URLs verbs headers authentication formats

  14. URLs verbs headers authentication formats validity

  15. URLs verbs headers authentication formats validity documentation

  16. DOCUMENTATION

  17. DOCUMENTATION (later)

  18. Part 1: URLs

  19. Make them versioned

  20. Make them versioned, hackable

  21. Make them versioned, hackable & meaningful

  22. http://api.com/v1/

  23. http://api.com/v1/users/

  24. http://api.com/v1/users/31337

  25. http://api.com/v1/users/31337/posts/

  26. Look at URLs from a consumer perspective

  27. They don’t care about internal implementation details

  28. Use common sense

  29. Don’t be afraid of the query string

  30. Use query arguments to filter output or for (some) alternate

    representations
  31. Good: searching & verbosity Bad: output format control (XML vs

    JSON)
  32. Part 2: Verbs

  33. (in terms of model operations)

  34. • GET = get() • PUT = setAll() / new

    Obj($id) • POST = new Obj() / doStuff() / set() • DELETE = delete() • HEAD ≈ getMetadata() • OPTIONS ≈ Reflection
  35. Must at least support GET/POST

  36. Can emulate PUT/DELETE

  37. For example: POST http://api.com/foo/456!PUT POST http://api.com/foo/123!DELETE

  38. Remember that POST can have side-effects and is never cached

  39. PUT and DELETE are idempotent, which means they can be

    repeated with same effect
  40. HEAD is rare and can probably be ignored

  41. OPTIONS is used by CORS, but otherwise rare

  42. CORS?

  43. Cross-Origin Resource Sharing

  44. A way to allow in-browser cross-origin XMLHTTPRequests Support: FF3.5+, Chrome

    4+, Safari 4+, Opera 12+, IE8+ (partial), IE10+ (full), iOS 3.2+, Android 2.1+ http://www.w3.org/TR/cors/ http://caniuse.com/cors
  45. Origin & Allow-Origin A way to allow in-browser cross-origin XMLHTTPRequests

    Support: FF3.5+, Chrome 4+, Safari 4+, Opera 12+, IE8+ (partial), IE10+ (full), iOS 3.2+, Android 2.1+ http://www.w3.org/TR/cors/ http://caniuse.com/cors
  46. Part 3: Headers

  47. Headers are important too!

  48. Some headers let you be clever

  49. Accept The MIME types the client will accept. No need

    to use file extensions to decide what content type to serve! Accept-Language The languages the client will accept. No need to ask clients or (worse) just assume English responses.
  50. Some headers reduce traffic (important for mobile)

  51. • ETag – A unique tag for the content •

    If-(None-)Match – Check ETag • If-Modified-Since – Is it newer? • Cache-Control – Can it be cached?
  52. Beware: some proxies may not pass custom headers

  53. Part 4: Authentication & Authorization

  54. OAuth2 over HTTPS

  55. Much simpler than OAuth 1.0

  56. Many libraries for OAuth2 for many platforms as it’s a

    popular standard
  57. If you really care about security use OAuth2-MAC

  58. OAuth2-MAC uses signatures instead of bearer tokens, so secrets stay

    secret
  59. Then again, the author of OAuth2 has now advised going

    back to OAuth 1.0a so YMMV
  60. Part 5: Formats

  61. Sane default: JSON, plus envelope with metadata

  62. { "meta": { "code": 2 , "dev_notes ": [ "This

    endpoint is deprecated" ] }, "response ": { ... } }
  63. Use XML if you must, or if users really want

    it
  64. HATEOAS tends to be verbose and people may hate you

    (unless they’re building an API explorer)
  65. At the very most, HATEOAS should be opt-in

  66. Don’t forget: mobile bandwidth is still very limited

  67. Timestamps • ISO-8601 2 12- 5- 3T19: : Z Human-readable,

    but needs parsing • UTC seconds since epoch: 1336 716 Easily machine-usable
  68. Should your API really be human-readable? It’s better to help

    your consumers.
  69. Part 6: Data Validity

  70. Allow your consumers to cache data whenever possible

  71. Encourage use of request headers: • GET: • If-Modified-Since •

    If-None-Match • POST/PUT/DELETE: • If-Unmodified-Since • If-Match
  72. Return useful response headers: • Last-Modified • Expires • ETag

    • Cache-Control
  73. Deal with preconditions and give correct response codes

  74. For example: ETag and Last-Modified can help prevent race conditions

  75. PUT /wiki/dealing -with -conflicts HTTP /1.1 Host: api.com If -Unmodified

    -Since: Sat , 18 Feb 2 12 11: 9:21 GMT If -Match: "x-rev -11294" Content -Type: text/html ... 412 Precondition Failed ETag: "x-rev -11467" Last -Modified: Sat , 25 Feb 2 12 14:42:53 GMT ...
  76. PUT /wiki/dealing -with -conflicts HTTP /1.1 Host: api.com If -Unmodified

    -Since: Sat , 18 Feb 2 12 11: 9:21 GMT If -Match: "x-rev -11294" Content -Type: text/html ... 412 Precondition Failed ETag: "x-rev -11467" Last -Modified: Sat , 25 Feb 2 12 14:42:53 GMT ...
  77. PUT /wiki/dealing -with -conflicts HTTP /1.1 Host: api.com If -Unmodified

    -Since: Sat , 18 Feb 2 12 11: 9:21 GMT If -Match: "x-rev -11294" Content -Type: text/html ... 412 Precondition Failed ETag: "x-rev -11467" Last -Modified: Sat , 25 Feb 2 12 14:42:53 GMT ...
  78. PUT /wiki/dealing -with -conflicts HTTP /1.1 Host: api.com If -Unmodified

    -Since: Sat , 18 Feb 2 12 11: 9:21 GMT If -Match: "x-rev -11294" Content -Type: text/html ... 412 Precondition Failed ETag: "x-rev -11467" Last -Modified: Sat , 25 Feb 2 12 14:42:53 GMT ...
  79. New status codes in RFC6585: 428 Precondition Required 429 Too

    Many Requests
  80. Part 7: Documentation

  81. Documentation is important

  82. If people can’t understand your API, they won’t use it

  83. Use examples liberally. . . and make sure they’re both

    up-to-date and correct!
  84. Assume nothing; explain everything

  85. Try getting people you know to build something using only

    your own API docs
  86. Thanks! http://dmi.me.uk/talks/ Feedback via Twitter: #apirocketsurgery or @dmi Built in

    L ATEX Inspired by: http://goo.gl/ mT55