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

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

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.

Dave Ingram

October 06, 2012
Tweet

More Decks by Dave Ingram

Other Decks in Technology

Transcript

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

    View Slide

  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

    View Slide

  3. Feedback/thoughts
    on Twitter:
    #apirocketsurgery
    (or @dmi)

    View Slide

  4. What this isn’t

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  8. There’s so much more!

    View Slide

  9. URLs

    View Slide

  10. URLs
    verbs

    View Slide

  11. URLs
    verbs
    headers

    View Slide

  12. URLs
    verbs
    headers
    authentication

    View Slide

  13. URLs
    verbs
    headers
    authentication
    formats

    View Slide

  14. URLs
    verbs
    headers
    authentication
    formats
    validity

    View Slide

  15. URLs
    verbs
    headers
    authentication
    formats
    validity
    documentation

    View Slide

  16. DOCUMENTATION

    View Slide

  17. DOCUMENTATION
    (later)

    View Slide

  18. Part 1: URLs

    View Slide

  19. Make them
    versioned

    View Slide

  20. Make them
    versioned,
    hackable

    View Slide

  21. Make them
    versioned,
    hackable &
    meaningful

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. Look at URLs from a
    consumer perspective

    View Slide

  27. They don’t care about
    internal implementation
    details

    View Slide

  28. Use common sense

    View Slide

  29. Don’t be afraid of
    the query string

    View Slide

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

    View Slide

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

    View Slide

  32. Part 2: Verbs

    View Slide

  33. (in terms of model
    operations)

    View Slide

  34. • GET = get()
    • PUT = setAll() / new Obj($id)
    • POST = new Obj() / doStuff() / set()
    • DELETE = delete()
    • HEAD ≈ getMetadata()
    • OPTIONS ≈ Reflection

    View Slide

  35. Must at least support GET/POST

    View Slide

  36. Can emulate PUT/DELETE

    View Slide

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

    View Slide

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

    View Slide

  39. PUT and DELETE are
    idempotent, which means
    they can be repeated
    with same effect

    View Slide

  40. HEAD is rare and
    can probably be ignored

    View Slide

  41. OPTIONS is used by CORS,
    but otherwise rare

    View Slide

  42. CORS?

    View Slide

  43. Cross-Origin Resource Sharing

    View Slide

  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

    View Slide

  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

    View Slide

  46. Part 3: Headers

    View Slide

  47. Headers are important too!

    View Slide

  48. Some headers let you be
    clever

    View Slide

  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.

    View Slide

  50. Some headers reduce traffic
    (important for mobile)

    View Slide

  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?

    View Slide

  52. Beware: some proxies may
    not pass custom headers

    View Slide

  53. Part 4: Authentication &
    Authorization

    View Slide

  54. OAuth2 over HTTPS

    View Slide

  55. Much simpler than OAuth 1.0

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  59. Then again, the author of OAuth2 has now
    advised going back to OAuth 1.0a so
    YMMV

    View Slide

  60. Part 5: Formats

    View Slide

  61. Sane default: JSON, plus
    envelope with metadata

    View Slide

  62. {
    "meta": {
    "code": 2 ,
    "dev_notes ": [
    "This endpoint is deprecated"
    ]
    },
    "response ": {
    ...
    }
    }

    View Slide

  63. Use XML if you must,
    or if users really want it

    View Slide

  64. HATEOAS tends to be verbose
    and people may hate you
    (unless they’re building an API explorer)

    View Slide

  65. At the very most,
    HATEOAS should be opt-in

    View Slide

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

    View Slide

  67. Timestamps
    • ISO-8601 2 12- 5- 3T19: : Z
    Human-readable, but needs parsing
    • UTC seconds since epoch: 1336 716
    Easily machine-usable

    View Slide

  68. Should your API really be
    human-readable?
    It’s better to help your
    consumers.

    View Slide

  69. Part 6: Data Validity

    View Slide

  70. Allow your consumers
    to cache data
    whenever possible

    View Slide

  71. Encourage use of request headers:
    • GET:
    • If-Modified-Since
    • If-None-Match
    • POST/PUT/DELETE:
    • If-Unmodified-Since
    • If-Match

    View Slide

  72. Return useful response headers:
    • Last-Modified
    • Expires
    • ETag
    • Cache-Control

    View Slide

  73. Deal with preconditions and
    give correct response codes

    View Slide

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

    View Slide

  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
    ...

    View Slide

  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
    ...

    View Slide

  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
    ...

    View Slide

  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
    ...

    View Slide

  79. New status codes in RFC6585:
    428 Precondition Required
    429 Too Many Requests

    View Slide

  80. Part 7: Documentation

    View Slide

  81. Documentation is important

    View Slide

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

    View Slide

  83. Use examples liberally. . .
    and make sure they’re both
    up-to-date and correct!

    View Slide

  84. Assume nothing;
    explain everything

    View Slide

  85. Try getting people you know
    to build something using
    only your own API docs

    View Slide

  86. Thanks!
    http://dmi.me.uk/talks/
    Feedback via Twitter:
    #apirocketsurgery or @dmi
    Built in L
    ATEX Inspired by: http://goo.gl/ mT55

    View Slide