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

REST API's: What I Wish Someone Had Told Me

weaverryan
October 30, 2014

REST API's: What I Wish Someone Had Told Me

Make no mistake, creating a "RESTful" API is hard work. It's packed full of theory and is's notorious for being difficult to find the fine line between getting it done and doing it "correctly". In this talk, we'll start through the must-know basics, like HTTP methods, status codes, resources and representations. But then, we'll turn to the harder stuff: hypermedia, links, hypermedia formats: what to worry about and what to leave behind. We'll also talk about error representations, serialization, custom methods (e.g. "buy" a book) and documentation for all of this (machine docs and human docs). In short, I'll show you what I wish I had always known: what pieces of REST to leave behind and some strategies on how to tackle the tough stuff that you *do* need.

weaverryan

October 30, 2014
Tweet

More Decks by weaverryan

Other Decks in Technology

Transcript

  1. by your friend:
    !
    Ryan Weaver
    @weaverryan
    REST API’s

    What I Wish Someone Had Told Me

    View Slide

  2. KnpUniversity.com

    github.com/weaverryan
    Who is this Hipster?
    > Lead for the Symfony documentation

    > KnpLabs US - Symfony Consulting,

    training, Kumbaya

    !
    > Writer for KnpUniversity.com Tutorials
    > Husband of the much more

    talented @leannapelham

    View Slide

  3. Chapter 0

    !
    I thought this

    would be easy
    @weaverryan

    View Slide

  4. @weaverryan

    View Slide

  5. @weaverryan
    GET /api/programmers/5 HTTP 1.1!
    Host: CodeBattles.io!
    Accept: application/json,text/html
    HTTP/1.1 200 OK!
    Content-Type: application/json!
    !
    {!
    "id": 5,!
    "nickname": "Namespacinator"!
    }

    View Slide

  6. @weaverryan
    Documentation
    Resources
    Hypermedia
    HATEOAS
    Testing
    Representations
    Resource State
    $MJFOU4UBUF
    Status Codes
    Links
    Embedded Resources
    Content-Negotation
    Location Header
    Idempotency
    PUT, POST, PATCH
    Pagination
    Filtering

    View Slide

  7. Chapter 1

    !
    Don’t be a hero
    @weaverryan
    !

    View Slide

  8. TIP! Research Services
    @weaverryan

    View Slide

  9. > design your API

    !
    > play with it

    !
    > implement

    !
    > use your design as a test
    @weaverryan

    View Slide

  10. View Slide

  11. Chapter 2

    !
    Documentation/design
    beats out implementation
    @weaverryan

    View Slide

  12. If you build it with no

    (or incorrect) docs…

    !
    people can’t use it
    womp womp
    @weaverryan

    View Slide

  13. TIP!
    Use a tool like

    Apiary or Behat
    @weaverryan

    View Slide

  14. @weaverryan

    View Slide

  15. @weaverryan

    View Slide

  16. @weaverryan

    View Slide

  17. knpuniversity.com/screencast/rest
    WebApiContext
    https://github.com/Behat/CommonContexts

    View Slide

  18. Chapter 3

    !
    Avoid the Hype

    (make it work)
    @weaverryan

    View Slide

  19. Let’s create a Programmer

    View Slide

  20. POST /api/programmers HTTP/1.1!
    Host: CodeBattles.io!
    Content-type: application/json!
    Accept: application/json,text/html!
    !
    {!
    "nickname": "ObjectOrienter",!
    "avatarNumber" : "2",!
    "tagLine": "Testing!"!
    }
    @weaverryan

    View Slide

  21. POST /api/programmers HTTP/1.1!
    Host: CodeBattles.io!
    Content-type: application/x-www-form-urlencoded!
    Accept: application/json,text/html!
    !
    nickname=ObjectOrienter&avatarN
    umber=2&tagLine=Testing
    @weaverryan

    View Slide

  22. HTTP/1.1 201 Created!
    Content-type: application/json!
    Location: /api/programmers/2!
    !
    {!
    "id": 2,!
    "nickname": "ObjectOrienter",!
    "avatarNumber" : "2",!
    "tagLine": "Testing!"!
    }
    @weaverryan

    View Slide

  23. REST
    !
    Representational

    State

    Transfer

    !
    WTH?
    @weaverryan

    View Slide

  24. TIP!
    Resource (URI)

    !
    vs.

    !
    Representation (HTML, json)
    … don’t over-think it
    @weaverryan

    View Slide

  25. @weaverryan
    resource
    representation

    (a drawing)

    View Slide

  26. @weaverryan
    resource
    representation

    (JSON)
    {!
    "programmers": [!
    { "name" : "Alice"},!
    { "name" : "Leanna" }!
    ]!
    }

    View Slide

  27. TIP!
    Resource State*
    *state means “data”
    @weaverryan

    View Slide

  28. REST
    ==
    1) A system where a client
    can change the data of 

    a resource

    !
    !
    2) The server can respond
    with the data of a resource
    @weaverryan

    View Slide

  29. TIP!
    Client State:
    !
    It’s just the “page”

    your API client is on
    @weaverryan

    View Slide

  30. Client:
    !
    impacts resource state/
    data by sending a
    representation of the
    desired state/data
    @weaverryan

    View Slide

  31. Server:
    !
    impacts client state by
    sending links that suggest
    what to do next

    (like an HTML page)
    @weaverryan

    View Slide

  32. TIP!
    Hypermedia:
    !
    it’s just JSON/XML with links
    … and sends back a special
    content-type header to tell the
    user about your format
    @weaverryan

    View Slide

  33. HAL+JSON
    content-type: application/hal+json
    http://phlyrestfully.readthedocs.org/en/latest/halprimer.html

    View Slide

  34. PNG (not hypermedia)
    content-type: image/png

    View Slide

  35. My Invention
    content-type: application/vnd.dapper+json
    {!
    "dapper_avatar": "http://i.vimeocdn.co
    "other_photos": [!
    "https://avatars1.githubusercontent.c
    ],!
    "homepage": "https://mwop.net/"!
    }!

    View Slide

  36. TIP! HATEOAS
    Hypermedia

    as

    the

    Engine

    of

    Application

    State
    Don’t believe
    the…
    @weaverryan

    View Slide

  37. add links to be more
    helpful to your client
    @weaverryan

    View Slide

  38. but don’t expect your API
    client to become self-aware
    and learn your API entirely
    by links… yet
    @weaverryan

    View Slide

  39. TIP!
    Request Representation

    !=
    Response Representation
    @weaverryan

    View Slide

  40. New Programer Request
    {!
    "nickname": "ObjectOrienter",!
    "avatarNumber" : "2",!
    "tagLine": "Testing!"!
    }
    @weaverryan

    View Slide

  41. New Programer Response
    @weaverryan
    {!
    "_links": {!
    "self": {!
    "href": "http://example.org/
    }!
    },!
    "id": "2",!
    "nickname": "ObjectOrienter",!
    "tagLine": "Testing!"!
    }!

    View Slide

  42. Chapter 4

    !
    It doesn’t have to be good

    It has to be consistent
    @weaverryan

    View Slide

  43. TIP!
    Use objects

    and a serializer
    JMSSerializer
    @weaverryan
    http://jmsyst.com/libs/serializer

    View Slide

  44. @weaverryan

    View Slide

  45. @weaverryan

    View Slide

  46. @weaverryan

    View Slide

  47. Serialization includes everything:
    !
    > Links

    > Embedded Resources

    > Pagination**

    > Filters**

    > Hypermedia Formatting
    ** BTW, use query parameters for pagination and filtering

    View Slide

  48. HATEOAS (library)

    View Slide

  49. @weaverryan

    View Slide

  50. TIP!
    application/problem+json

    !
    Consistency with errors
    @weaverryan

    View Slide

  51. @weaverryan
    HTTP/1.1 400 Bad Request
    Content-Type: application/problem+json
    !
    {
    "errors":
    {"nickname":"Enter a clever nickname"},
    "status":400,
    "type": "
    http://example.com
    /docs/errors#validation_error”,
    "title":"There was a validation error”
    }

    View Slide

  52. @weaverryan

    View Slide

  53. Return this format in *all*
    error situations
    And add exception
    handlers to guarantee this

    View Slide

  54. @weaverryan
    Silex! Oh crap, something went wild!

    View Slide

  55. @weaverryan
    Let’s keep our head’s straight.
    Create that nice ApiProblem object.

    View Slide

  56. @weaverryan
    type should be a URL. It’s about making
    it obvious what how to find out more

    View Slide

  57. @weaverryan
    all gravy now!

    View Slide

  58. TIP!
    Be consistent, but simple, with status codes
    200: most response

    201: after creating a resource

    204: a 200, but blank response (e.g. delete resource)

    400: validation errors or bad data format

    401/403: Unauthorized/Access Denied

    500: things are not good
    202: If the resource will be created later

    422: Could be used for validation errors

    View Slide

  59. TIP!
    Don’t get obsessed with
    multiple formats and

    content-type negotiation
    @weaverryan

    View Slide

  60. TIP!
    Don’t get obsessed with
    *accepting* multiple input
    formats

    !
    “we support sending json, XML or www-
    form-urlencoded data!”
    @weaverryan
    Why?

    View Slide

  61. TIP!
    Use OAuth? Or maybe a
    simple token-based
    authentication
    … sure, if you have bigger requirement,

    use something bigger
    @weaverryan

    View Slide

  62. TIP!
    Don’t worry about versioning

    unless you really have the
    problem.
    @weaverryan

    View Slide

  63. POST, PUT, Idempotency
    @weaverryan

    View Slide

  64. Idempotency:
    !
    Is it guaranteed to be safe if

    I accidentally make a

    request twice in a row?
    @weaverryan

    View Slide

  65. POST: Not Idempotent

    PUT: Idempotent
    @weaverryan
    blah blah…

    View Slide

  66. TIP!
    PUT if *both* of the

    following are true:
    1) The request is idempotent

    !
    2) The URI is to the resource being updated
    … otherwise, use POST

    View Slide

  67. @weaverryan
    /api/programmers POST Not Idempotent
    /api/programers/5 PUT
    /api/programmers/5/avatar PUT
    /api/programmers/5/sleep POST
    URI is not to resource
    being updated
    POST != idempotent, but making a request
    twice doesn’t *need* to have a side-effect

    View Slide

  68. Editing
    PUT: Replace

    (nullify missing fields)

    !
    PATCH: Update

    (send directions)
    @weaverryan

    View Slide

  69. TIP!
    > Use either PATCH or PUT

    !
    > Ignore how they’re supposed to work

    !
    > Document clearly how you’re using them
    @weaverryan

    View Slide

  70. @weaverryan
    GitHub API

    View Slide

  71. REST
    !
    Keep it Simple
    @weaverryan

    View Slide

  72. 1) Research Tools
    @weaverryan

    View Slide

  73. 2) Decide how you’ll test and
    generate your documentation
    before coding
    @weaverryan

    View Slide

  74. 3) Don’t let the Resource,
    Representation, State jargon
    confuse you
    @weaverryan

    View Slide

  75. 4) Add links to help your
    client, but don’t go for
    HATEOAS
    @weaverryan

    View Slide

  76. 5) Consistency is king 

    (use a serializer)
    @weaverryan

    View Slide

  77. 6) Use PUT if it follows the 2
    rules, POST as the catch-all
    @weaverryan

    View Slide

  78. And celebrate because you
    just survived your API!
    @weaverryan

    View Slide

  79. Thanks!
    Ryan Weaver
    @weaverryan
    KnpUniversity.com
    PHP
    , Behat, Twig, OO, etc Tutorial Screencasts
    https://joind.in/12084

    View Slide