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

API Pain Points - ConFoo 2015

Phil Sturgeon
February 19, 2015
1.1k

API Pain Points - ConFoo 2015

It is becoming ever more common for server-side developers to build APIs thanks to the rise of front-end JavaScript frameworks, iPhone applications and generally API-centric architectures. Grabbing data source and shoving it out as JSON sounds easy, but there is so much more. Surviving changes in business logic, database schema updates, using serialization to avoid directly outputting database structure, JSON-API and loads more.

Phil Sturgeon

February 19, 2015
Tweet

Transcript

  1. A P I PA I N - P O I

    N T S G E T T I N G T H I N G S W R O N G F O R F U N A N D P R O F I T @ P H I L S T U R G E O N # C O N F O O 2 0 1 5
  2. A R C H I T E C T U

    R E O L D S C H O O L
  3. D ATA B A S E S E E D

    I N G L E A V E Y O U R C U S T O M E R S A L O N E
  4. E N D P O I N T T H

    E O RY N A M I N G T H I N G S I S H A R D
  5. P L U R A L V S I N

    G U L A R ? C O N S I S T E N C Y I S K I N G /user/23 /users
  6. P L U R A L V S I N

    G U L A R ? C O N S I S T E N C Y I S K I N G /opportunity/43 /opportunities
  7. P L U R A L V S I N

    G U L A R ? C O N S I S T E N C Y I S K I N G /person/dave /people
  8. P L U R A L V S I N

    G U L A R ? C O N S I S T E N C Y I S K I N G /places /places/12 /places/12/checkins /places/12/checkins/34 /checkins/34
  9. N O N E E D F O R S

    E O Q U E RY S T R I N G S A R E F I N E /users/active/true /users?active=true
  10. A U T O - I N C R E

    M E N T = B A D C T R L + S Y O U R W E B S I T E /checkins/1 /checkins/2 /checkins/2369 … /checkins/3
  11. A U T O - I N C R E

    M E N T = B A D C T R L + S Y O U R W E B S I T E github.com/zackkitzmiller/tiny-php $tiny = new \ZackKitzmiller\Tiny('lDpuU74QNH6B'); ! echo $tiny->to(5); // E ! echo $tiny->from('E'); // 5
  12. A U T O - I N C R E

    M E N T = B A D C T R L + S Y O U R W E B S I T E ! use Rhumsaa\Uuid\Uuid; use Rhumsaa\Uuid\Exception; ! $uuid4 = Uuid::uuid4(); ! echo $uuid4; // 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a github.com/ramsey/uuid
  13. W H I C H M E T H O

    D S V E R B S O U P List GET /users Read GET /users/X Update PUT /users/X Update PATCH /users/X Create POST /users Delete DELETE /users/X Image PUT /users/X/image Images POST /users/X/images Favourites GET /users/X/images
  14. H T T P V E R B S M

    AT T E R H O N E S T LY Dont be @jamiehannaford. That sounds like a bad day.
  15. P I C K T H E R I G

    H T F O R M AT B E F O R E Y O U S E T O U T
  16. F O R M PAY L O A D S

    J U S T S E N D J S O N foo=something&bar[baz]=thing &bar[stuff]=junk&bar=true 24
  17. H A C K Y PAY L O A D

    S N O T L I K E T H A T
  18. R E A L J S O N PAY L

    O A D S T H N X !
  19. R E A D I N G R E A

    L D ATA I S E A S Y T H E H T T P WA Y Lazy $_POST[‘foo’]; Proper json_decode(file_get_contents(‘php://input')); Proper in Laravel Input::json(‘foo’);
  20. E R R O R M E S S A

    G E S B E I N G W R O N G C O R R E C T LY http://www.funcage.com/blog/page/439/
  21. 2 0 0 I S N O T T H

    E O N LY S U C C E S S K N O W Y O U R C O D E S if ($statusCode != 200) { throw new Exception('AAGHH!!'); }
  22. 2xx is all about success 3xx is all about redirection

    4xx is all about client errors 5xx is all about service errors
  23. 200 - Generic everything is OK 201 - Created something

    OK 202 - Accepted but is being processed async 400 - Bad Request (Validation?) 401 - Unauthorized 403 - Current user is forbidden 404 - That URL is not a valid route 405 - Method Not Allowed 410 - Data has been deleted, deactivated, suspended, etc 500 - Something unexpected happened and it is the APIs fault 503 - API is not here right now, please try again later
  24. C L E A R , H U M A

    N E R R O R S W H A T H A P P E N E D { "error": { "errors": [ { "domain": "youtube.parameter", "reason": "missingRequiredParameter", "message": "No filter selected.", "locationType": "parameter", "location": "" } ], "code": 400, "message": "No filter selected." } }
  25. E R R O R S S H O U

    L D M A K E S E N S E W H A T H A P P E N E D &mine=true "reason": "missingRequiredParameter", "message": "No filter selected.", … WTF
  26. S U P P L E M E N T

    H T T P C O D E S W H A T H A P P E N E D { "error": { "type": "OAuthException", "message": "Session has expired at unix time 1385243766. The current unix time is 1385848532" } }
  27. S U P P L E M E N T

    H T T P C O D E S W H A T H A P P E N E D { "error": { "message": "(#210) Subject must be a page.", "type": "OAuthException", "code": 210 } }
  28. S U P P L E M E N T

    H T T P C O D E S W H A T H A P P E N E D { "error": { "message": "(#210) Subject must be a page.", "type": "OAuthException", "code": 210, "url": “http://developers.facebook.com/errors#210“ } }
  29. E R R O R S A R E A

    S O LV E D P R O B L E M U S E A N E X I S T I N G F O R M A T jsonapi.org/format/#errors mnot.net/blog/2013/05/15/http_problem
  30. O A U T H 2 C A N D

    O A L O T PA S S W O R D S , I M P L I C I T, S O C I A L L O G I N S …
  31. FA C E B O O K … Y O

    U B # % @ * D S ! ! ! S E R I O U S LY Refresh Tokens? ! Lol
  32. Y O U T U B E … Y O

    U S E M I - B # % @ * D S ! ! ! S T I L L S E R I O U S LY Refresh Tokens? ! Kinda
  33. P R E S E N TAT I O N

    L AY E R D O N T L E T U S E R S B E H I N D T H E C U R TA I N
  34. ! return Places::all(); P R E S E N TAT

    I O N L AY E R D O N T L E T U S E R S B E H I N D T H E C U R TA I N
  35. T R A N S F O R M E

    R S … A S S E M B L E ! public function transform(Book $book) { return [ 'id' => (int) $book->id, 'title' => $book->title, 'year' => $book->yr, ‘created' => (string) $book->created_at, ]; } fractal.thephpleague.com
  36. F L E X I B L E R E

    S P O N S E S S T O P Y O U R I P H O N E D E V C O M P L A I N I N G GET /checkins/dsfXte ?include=place,user,activity
  37. PA G I N AT E D A TA G

    R O W S FA S T { "data": [ ... ], "cursors": { "after": "MTI=", "next_url": "https://api.example.com/places ?cursor=MTI%3" } }
  38. D E F I N E A L I M

    I T R A N G E PA G I N A T I O N D D O S if ($limit < 1 || $limit > 100) { $limit = 100; }
  39. A U T O M AT E T E S

    T I N G I F Y O U L O V E Y O U R J O B http://www.engineersgotblued.com/
  40. P H P U N I T + B E

    H AT http://www.bil-jac.com/bestfriendsclub.php
  41. Scenario: Find a merchant When I request "GET /moments/1" Then

    I get a "200" response And scope into the "data" property And the properties exist: """ id title year created """
  42. Scenario: Try to find an ` checkin When I request

    "GET /checkins/nope" Then I get a "404" response
  43. Scenario:Wrong Arguments for user follow Given I have the payload:

    """ {"is_following": "foo"} """ When I request "PUT /users/1” Then I get a "400" response Not a boolean
  44. V E R S I O N I N G

    / V 1 / D O E S N T C O U N T https://api.example.com/v1/places
  45. V E R S I O N I N G

    / V 1 / D O E S N T C O U N T https://api-v1.example.com/places
  46. V E R S I O N I N G

    / V 1 / D O E S N T C O U N T Accept: application/vnd.example+json; version=1 Accept: application/vnd.example+json; version=2
  47. V E R S I O N I N G

    / V 1 / D O E S N T C O U N T Accept: application/vnd.example.user+json; version=1 Accept: application/vnd.example.user+json; version=2
  48. V E R S I O N I N G

    / V 1 / D O E S N T C O U N T Copy Facebook ! Maybe? ! THIS ONE TIME! Facebook ruined the one good thing they ever did
  49. E V E RY T H I N G I

    S W R O N G D O N T B E T H A T G U Y troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html