Slide 1

Slide 1 text

Get Some REST: Best RESTful API Practices

Slide 2

Slide 2 text

About Me 2 • Lorna Jane Mitchell • PHP Consultant/Developer • API Specialist • Author of PHP Master • Twitter: @lornajane • Website: http://lornajane.net

Slide 3

Slide 3 text

About REST 3 • REpresentational State Transfer • Everything is a resource • Representations get passed around • Great for data-driven applications

Slide 4

Slide 4 text

Not RESTful 4 Clues that your service isn’t RESTful: • It has a single endpoint

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

RESTful != Useful

Slide 10

Slide 10 text

Best Practices

Slide 11

Slide 11 text

Use Existing Skills/Tools

Slide 12

Slide 12 text

Existing Skills 8

Slide 13

Slide 13 text

MVC Applications 9 Model-View-Controller becomes Model-Controller-Output Handler

Slide 14

Slide 14 text

MVC Applications 10 Model-View-Controller becomes Model-Controller-Output Handler output controller model index

Slide 15

Slide 15 text

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; } }

Slide 16

Slide 16 text

Meaningful URL Structure

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Considering Sub-Resources 16 Common pitfall: http://example.com/articles/42/activate

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Hypermedia

Slide 28

Slide 28 text

Hypermedia 18 GET http://api.joind.in/v2.1/events/853

Slide 29

Slide 29 text

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]);

Slide 30

Slide 30 text

Content Negotiation

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Content Negotiation Confession 22 The joind.in API also allows ?format=json as an override

Slide 33

Slide 33 text

Error Handling

Slide 34

Slide 34 text

Simple Error Rules for Service Providers 24 • Use expected format • Give meaningful messages • Be consistent

Slide 35

Slide 35 text

Exceptions Help Consistency 25 output controller model index

Slide 36

Slide 36 text

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');

Slide 37

Slide 37 text

When Things Go Wrong

Slide 38

Slide 38 text

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"

Slide 39

Slide 39 text

Protecting Yourself

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Respect the Danger 31 Website Digital Identity API Product API Database Mobile Application logic layer

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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"

Slide 44

Slide 44 text

Best Practice for RESTful Applications 34 • Use existing tools, skills and conventions • Deliver what’s useful to your users • Plan defensively

Slide 45

Slide 45 text

Questions?

Slide 46

Slide 46 text

Thanks! 36 @lornajane http://lornajane.net