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

F5dfeeef276fcfd4751f4063487a5a3f?s=47 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.



October 30, 2014


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

    I Wish Someone Had Told Me
  2. Who is this Hipster? > Lead for the

    Symfony documentation
 > KnpLabs US - Symfony Consulting, training, Kumbaya ! > Writer for Tutorials > Husband of the much more talented @leannapelham
  3. Chapter 0 ! I thought this would be easy @weaverryan

  4. @weaverryan

  5. @weaverryan GET /api/programmers/5 HTTP 1.1! Host:! Accept: application/json,text/html HTTP/1.1

    200 OK! Content-Type: application/json! ! {! "id": 5,! "nickname": "Namespacinator"! }
  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
  7. Chapter 1 ! Don’t be a hero @weaverryan !

  8. TIP! Research Services @weaverryan

  9. > design your API ! > play with it !

    > implement ! > use your design as a test @weaverryan
  10. None
  11. Chapter 2 ! Documentation/design beats out implementation @weaverryan

  12. If you build it with no (or incorrect) docs… !

    people can’t use it womp womp @weaverryan
  13. TIP! Use a tool like Apiary or Behat @weaverryan

  14. @weaverryan

  15. @weaverryan

  16. @weaverryan

  17. WebApiContext

  18. Chapter 3 ! Avoid the Hype (make it work) @weaverryan

  19. Let’s create a Programmer

  20. POST /api/programmers HTTP/1.1! Host:! Content-type: application/json! Accept: application/json,text/html! !

    {! "nickname": "ObjectOrienter",! "avatarNumber" : "2",! "tagLine": "Testing!"! } @weaverryan
  21. POST /api/programmers HTTP/1.1! Host:! Content-type: application/x-www-form-urlencoded! Accept: application/json,text/html! !

    nickname=ObjectOrienter&avatarN umber=2&tagLine=Testing @weaverryan
  22. HTTP/1.1 201 Created! Content-type: application/json! Location: /api/programmers/2! ! {! "id":

    2,! "nickname": "ObjectOrienter",! "avatarNumber" : "2",! "tagLine": "Testing!"! } @weaverryan
  23. REST ! Representational State Transfer ! WTH? @weaverryan

  24. TIP! Resource (URI) ! vs. ! Representation (HTML, json) …

    don’t over-think it @weaverryan
  25. @weaverryan resource representation (a drawing)

  26. @weaverryan resource representation (JSON) {! "programmers": [! { "name" :

    "Alice"},! { "name" : "Leanna" }! ]! }
  27. TIP! Resource State* *state means “data” @weaverryan

  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
  29. TIP! Client State: ! It’s just the “page” your API

    client is on @weaverryan
  30. Client: ! impacts resource state/ data by sending a representation

    of the desired state/data @weaverryan
  31. Server: ! impacts client state by sending links that suggest

    what to do next (like an HTML page) @weaverryan
  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
  33. HAL+JSON content-type: application/hal+json

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

  35. My Invention content-type: application/vnd.dapper+json {! "dapper_avatar": " "other_photos": [! "https://avatars1.githubusercontent.c

    ],! "homepage": ""! }!
  36. TIP! HATEOAS Hypermedia as the Engine of Application State Don’t

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

  38. but don’t expect your API client to become self-aware and

    learn your API entirely by links… yet @weaverryan
  39. TIP! Request Representation != Response Representation @weaverryan

  40. New Programer Request {! "nickname": "ObjectOrienter",! "avatarNumber" : "2",! "tagLine":

    "Testing!"! } @weaverryan
  41. New Programer Response @weaverryan {! "_links": {! "self": {! "href":

    " }! },! "id": "2",! "nickname": "ObjectOrienter",! "tagLine": "Testing!"! }!
  42. Chapter 4 ! It doesn’t have to be good It

    has to be consistent @weaverryan
  43. TIP! Use objects and a serializer JMSSerializer @weaverryan

  44. @weaverryan

  45. @weaverryan

  46. @weaverryan

  47. Serialization includes everything: ! > Links > Embedded Resources >

    Pagination** > Filters** > Hypermedia Formatting ** BTW, use query parameters for pagination and filtering
  48. HATEOAS (library)

  49. @weaverryan

  50. TIP! application/problem+json ! Consistency with errors @weaverryan

  51. @weaverryan HTTP/1.1 400 Bad Request Content-Type: application/problem+json ! { "errors":

    {"nickname":"Enter a clever nickname"}, "status":400, "type": " /docs/errors#validation_error”, "title":"There was a validation error” }
  52. @weaverryan

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

    handlers to guarantee this
  54. @weaverryan Silex! Oh crap, something went wild!

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

  56. @weaverryan type should be a URL. It’s about making it

    obvious what how to find out more
  57. @weaverryan all gravy now!

  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
  59. TIP! Don’t get obsessed with multiple formats and content-type negotiation

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

    “we support sending json, XML or www- form-urlencoded data!” @weaverryan Why?
  61. TIP! Use OAuth? Or maybe a simple token-based authentication …

    sure, if you have bigger requirement, use something bigger @weaverryan
  62. TIP! Don’t worry about versioning unless you really have the

    problem. @weaverryan
  63. POST, PUT, Idempotency @weaverryan

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

    accidentally make a request twice in a row? @weaverryan
  65. POST: Not Idempotent
 PUT: Idempotent @weaverryan blah blah…

  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
  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
  68. Editing PUT: Replace (nullify missing fields) ! PATCH: Update (send

    directions) @weaverryan
  69. TIP! > Use either PATCH or PUT
 ! > Ignore

    how they’re supposed to work
 ! > Document clearly how you’re using them @weaverryan
  70. @weaverryan GitHub API

  71. REST ! Keep it Simple @weaverryan

  72. 1) Research Tools @weaverryan

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

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

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

    for HATEOAS @weaverryan
  76. 5) Consistency is king 
 (use a serializer) @weaverryan

  77. 6) Use PUT if it follows the 2 rules, POST

    as the catch-all @weaverryan
  78. And celebrate because you just survived your API! @weaverryan

  79. Thanks! Ryan Weaver @weaverryan PHP , Behat, Twig, OO,

    etc Tutorial Screencasts