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

Get Some REST: Best RESTful API Practices

Get Some REST: Best RESTful API Practices

A handful of pointers for making good RESTful services, or at least avoiding the worst of the pitfalls. Code examples in PHP, this talk was originally given at OSCON 2012

Lorna Mitchell

July 19, 2012
Tweet

More Decks by Lorna Mitchell

Other Decks in Technology

Transcript

  1. About Me 2 • Lorna Jane Mitchell • PHP Consultant/Developer

    • API Specialist • Author of PHP Master • Twitter: @lornajane • Website: http://lornajane.net
  2. About REST 3 • REpresentational State Transfer • Everything is

    a resource • Representations get passed around • Great for data-driven applications
  3. Not RESTful 4 Clues that your service isn’t RESTful: •

    It has a single endpoint • All requests are POSTs
  4. Not RESTful 4 Clues that your service isn’t RESTful: •

    It has a single endpoint • All requests are POSTs • Response metadata is in the body, not header
  5. Not RESTful 4 Clues that your service isn’t RESTful: •

    It has a single endpoint • All requests are POSTs • Response metadata is in the body, not header • There are verbs in the URL
  6. Not RESTful 4 Clues that your service isn’t RESTful: •

    It has a single endpoint • All requests are POSTs • Response metadata is in the body, not header • There are verbs in the URL • The URL includes method names
  7. Output Handlers: JSON 11 class JsonView extends ApiView { public

    function render($content) { header('Content-Type: application/json; charset=utf8'); echo $this->buildOutput($content); return true; } /** * Function to build output, can be used by JSON and JSONP */ protected function buildOutput ($content) { $content = $this->addCount($content); $retval = json_encode($content, JSON_NUMERIC_CHECK); return $retval; } }
  8. Meaningful URLs 13 What would you expect to find at:

    http://api.joind.in/v2.1/events?filter=upcoming
  9. Meaningful URLs 13 What would you expect to find at:

    http://api.joind.in/v2.1/events?filter=upcoming http://api.joind.in/v2.1/events/853
  10. Meaningful URLs 13 What would you expect to find at:

    http://api.joind.in/v2.1/events?filter=upcoming http://api.joind.in/v2.1/events/853 http://api.joind.in/v2.1/events/853/talks
  11. Meaningful URLs 13 What would you expect to find at:

    http://api.joind.in/v2.1/events?filter=upcoming http://api.joind.in/v2.1/events/853 http://api.joind.in/v2.1/events/853/talks http://api.joind.in/v2.1/talks/6232
  12. Meaningful URLs 13 What would you expect to find at:

    http://api.joind.in/v2.1/events?filter=upcoming http://api.joind.in/v2.1/events/853 http://api.joind.in/v2.1/events/853/talks http://api.joind.in/v2.1/talks/6232 http://api.joind.in/v2.1/talks/6232/comments
  13. Verbs and URLs 14 These URLs give us representations of

    either resources or collections of resources We use HTTP verbs to operate on these resources Verb Collection Resource GET fetch resources fetch resource POST create a resource in this collection PUT create or update a resource here PATCH update part of a resource DELETE delete a resource
  14. Identifying Resources 15 What is a "resource"? • Maybe a

    database row • Maybe an item with some information from other tables • Talks also show speaker names, for example • Maybe a sub-resource
  15. Considering Sub-Resources 16 Common pitfall: http://example.com/articles/42/activate We have two options

    GET http://example.com/articles/42, change the "active" flag, and PUT it back
  16. Considering Sub-Resources 16 Common pitfall: http://example.com/articles/42/activate We have two options

    GET http://example.com/articles/42, change the "active" flag, and PUT it back Make a subresource, then you can just work with http://example.com/articles/42/active
  17. Hypermedia 19 • Consumers can follow links rather than construct

    them • Providers can change link structures $event_url = 'http://api.joind.in/v2.1/events/853'; $event_data = json_decode( file_get_contents($event_url), TRUE); // get event talks $talks = json_decode( file_get_contents($event_data['events'][0]['talks_uri']), TRUE ); print_r($talks['talks'][0]);
  18. Content Negotiation 21 We use the Accept and Content-Type headers

    to agree what formats to use. Common examples: • application/json • application/xml • text/html Next stage: use Media Types for custom/versioned representations
  19. Simple Error Rules for Service Providers 24 • Use expected

    format • Give meaningful messages • Be consistent
  20. Exceptions Help Consistency 26 function handle_exception($e) { // pull the

    correct format before we bail global $request; header("Status: " . $e->getCode(), false, $e->getCode()); $request->view->render(array($e->getMessage())); } set_exception_handler('handle_exception');
  21. Crisis Strategies 28 • Lots of logging! • Logging rather

    than debug output if the client expects JSON • Proxy or network analyser • Inspects traffic without application changes • e.g. Wireshark or Charles proxy • Drop back to last known good outcome • Increase complexity in "baby steps"
  22. Isolate External Dependencies 30 Never call an API from your

    own code - have a class that wraps it. You can: • cache results if it is slow/flaky • replace it in one place later, if needed • write tests to check the API is still doing what you expect • write a mock object to replace it with for your own tests
  23. Respect the Danger 31 Website Digital Identity API Product API

    Database Mobile Application logic layer
  24. Respect the Danger 32 abyss Website Digital Identity API Product

    API Database Mobile Application logic layer
  25. Deliver on Time 33 How to estimate for API integration?

    • You can’t estimate an unknown task • Invest time in a prototype • In agile speak, a "spike"
  26. Best Practice for RESTful Applications 34 • Use existing tools,

    skills and conventions • Deliver what’s useful to your users • Plan defensively