Get Some REST: Best RESTful API Practices
About Me • Lorna Jane Mitchell • PHP Consultant/Developer • API Specialist • Author of PHP Master • Twitter: @lornajane • Website: http://lornajane.net 2
About REST • REpresentational State Transfer • Everything is a resource • Representations get passed around • Great for data-driven applications 3
Not RESTful Clues that your service isn’t RESTful: • It has a single endpoint 4
Not RESTful Clues that your service isn’t RESTful: • It has a single endpoint • All requests are POSTs 4
Not RESTful Clues that your service isn’t RESTful: • It has a single endpoint • All requests are POSTs • Response metadata is in the body, not header 4
Not RESTful 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 4
Not RESTful 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 4
RESTful != Useful
Best Practices
Use Existing Skills/Tools
Existing Skills 8
MVC Applications Model-View-Controller becomes Model-Controller-Output Handler 9
MVC Applications Model-View-Controller becomes Model-Controller-Output Handler index output controller model 10
Output Handlers: JSON 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; } } 11
Meaningful URL Structure
Meaningful URLs What would you expect to find at: http://api.joind.in/v2.1/events?filter=upcoming 13
Meaningful URLs What would you expect to find at: http://api.joind.in/v2.1/events?filter=upcoming http://api.joind.in/v2.1/events/853 13
Meaningful URLs 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 13
Meaningful URLs 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 13
Meaningful URLs 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 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 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 Common pitfall: http://example.com/articles/42/activate 16
Considering Sub-Resources 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 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 16
Hypermedia
Hypermedia GET http://api.joind.in/v2.1/events/853 18
Hypermedia • 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]); 19
Content Negotiation
Content Negotiation 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 21
Content Negotiation Confession The joind.in API also allows ?format=json as an override 22
Error Handling
Simple Error Rules for Service Providers • Use expected format • Give meaningful messages • Be consistent 24
Exceptions Help Consistency index output controller model 25
Exceptions Help Consistency 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'); 26
When Things Go Wrong
Crisis Strategies • 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" 28
Protecting Yourself
Isolate External Dependencies 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 30
Respect the Danger Website Mobile Application logic layer Digital Identity API Product API Database 31
Respect the Danger Website Mobile Application logic layer abyss Digital Identity API Product API Database 32
Deliver on Time How to estimate for API integration? • You can’t estimate an unknown task • Invest time in a prototype • In agile speak, a "spike" 33
Best Practice for RESTful Applications • Use existing tools, skills and conventions • Deliver what’s useful to your users • Plan defensively 34
Questions?
Thanks! @lornajane http://lornajane.net 36
Recommend
More recommend