SlideShare a Scribd company logo
A P I P A 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 2 0 1 4
API Pain Points (PHPNE)
API Pain Points (PHPNE)
A R C H I T E C T U R E
O L D S C H O O L
API Pain Points (PHPNE)
http://girlsgotsole.com/blog/thankful-thursday-rest-days/
D A T A 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
E N D P O I N T T H E O R Y
N A M I N G T H I N G S I S H A R D
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
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
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
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
N O N E E D F O R S E O
Q U E R Y S T R I N G S A R E F I N E
/users/active/true
/users?active=true
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
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 ZackKitzmillerTiny('lDpuU74QNH6B');
echo $tiny->to(5);
// E
echo $tiny->from('E');
// 5
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 RhumsaaUuidUuid;
use RhumsaaUuidExceptio
$uuid4 = Uuid::uuid4();
echo $uuid4;
// 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a
github.com/ramsey/uuid
H T T P V E R B S M A T T E R
H O N E S T L Y
Dont be @jamiehannaford.
That sounds like a bad day.
F O R M P A Y 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=true18
H A C K Y P A Y L O A D S
N O T L I K E T H A T
R E A L J S O N P A Y L O A D S
T H N X !
R E A D I N G R E A L D A T A I S
E A S Y
T H E H T T P W A Y
json_decode($_POST['stupid-json']);
json_decode(file_get_contents(‘php://input'));
Input::get(‘foo’);
API Pain Points (PHPNE)
2 0 0 I S N O T T H E O N L Y
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!!');
}
2xx is all about success
3xx is all about redirection
4xx is all about client errors
5xx is all about service errors
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
418 - I am a Teapot
http://httpstatus.es/418
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."
}
}
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
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 138
}
}
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
}
}
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“
}
}
O A U T H 2 . 0
thephpleague.com
github.com/thephpleague/oauth2-server
O A U T H 2 C A N D O A L O T
P A 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 …
U S E S S L
L O L
E X C E P T F O R …
F A C E B O O K … Y O U
B # % @ * D S ! ! !
S E R I O U S L Y
Refresh Tokens?
Lol
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 L Y
Refresh Tokens?
Kinda
P R E S E N T A T I O N L A Y 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 T A I N
return Places::all();
P R E S E N T A T I O N L A Y 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 T A I N
API Pain Points (PHPNE)
API Pain Points (PHPNE)
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
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
P A G I N A T E
D A T A G R O W S F A S T
{
"data": [
...
],
"cursors": {
"after": "MTI=",
"next_url": "https://api.example.com/places
?cursor=MTI%3"
}
}
D E F I N E A L I M I T R A N G E
P A G I N A T I O N D D O S
if ($limit < 1 || $limit > 100) {
$limit = 100;
}
A U T O M A T 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/
P H P U N I T + B E H A T
http://www.bil-jac.com/bestfriendsclub.php
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
"""
Scenario: Try to find an ` checkin
When I request "GET /checkins/nope"
Then I get a "404" response
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
apiblueprint.org
API Pain Points (PHPNE)
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
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
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
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
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
E V E R Y 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
leanpub.com/build-apis-you-wont-hate/c/TOONARMY

More Related Content

PPT
Api pain points
PPTX
Inside a Digital Collection: Historic Clothing in Omeka
PDF
Porque VIM?
PDF
Testing TYPO3 Applications
PDF
Semantic Web & TYPO3
PDF
Using HTML5 for a great Open Web
PDF
Noah Brier: How to build web apps
PDF
How to Build a Web App (for Non-Programmers)
Api pain points
Inside a Digital Collection: Historic Clothing in Omeka
Porque VIM?
Testing TYPO3 Applications
Semantic Web & TYPO3
Using HTML5 for a great Open Web
Noah Brier: How to build web apps
How to Build a Web App (for Non-Programmers)

What's hot (19)

KEY
Web Development with CoffeeScript and Sass
PDF
PHP Backdoor: The rise of the vuln
PPT
wreewrer
PDF
Php web backdoor obfuscation
PPT
Concept History
PPTX
Twas the night before Malware...
PDF
H4x0rs gonna hack
PDF
Rooted 2010 ppp
PDF
Code obfuscation, php shells & more
PDF
SULTHAN's - PHP MySQL programs
PDF
SmartData Webinar Slides JSON-LD
PDF
Diary of a Hack
KEY
Yql && Raphaël
PDF
Building Things Fast - and getting approval
PDF
Easy logins for Ruby web applications
PPT
Unix shell scripting basics
PDF
Tasc workshop presentation
PPT
YQL - Christian Heilmann Open Hack London presentation
PDF
Yahoo is open to developers
Web Development with CoffeeScript and Sass
PHP Backdoor: The rise of the vuln
wreewrer
Php web backdoor obfuscation
Concept History
Twas the night before Malware...
H4x0rs gonna hack
Rooted 2010 ppp
Code obfuscation, php shells & more
SULTHAN's - PHP MySQL programs
SmartData Webinar Slides JSON-LD
Diary of a Hack
Yql && Raphaël
Building Things Fast - and getting approval
Easy logins for Ruby web applications
Unix shell scripting basics
Tasc workshop presentation
YQL - Christian Heilmann Open Hack London presentation
Yahoo is open to developers
Ad

Similar to API Pain Points (PHPNE) (20)

PPT
Api pain points
KEY
Api anti patterns
PPTX
API Design - 3rd Edition
PDF
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
PDF
Resource-Oriented Web Services
KEY
Pragmatic RESTful API Design: Apigee Webinar
ODP
NEPHP '13: Pragmatic API Development
PDF
The Art of API Design - PHP Tek 2025, Chris Tankersley
PDF
Создание API, которое полюбят разработчики. Глубокое погружение
ZIP
The Power of Open Data
PDF
2012 03 27_philly_jug_rewrite_static
PPT
PHP Server side restful API - linkedin
PDF
Restful design at work v2.0
KEY
API Best Practices
PDF
BeJUG JAX-RS Event
PDF
What’s Your Problem?
PDF
REST in ( a mobile ) peace @ WHYMCA 05-21-2011
PDF
So you think you know REST - DPC11
PDF
Profiling Web Archives IIPC GA 2015
PDF
Frans Rosén Keynote at BSides Ahmedabad
Api pain points
Api anti patterns
API Design - 3rd Edition
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
Resource-Oriented Web Services
Pragmatic RESTful API Design: Apigee Webinar
NEPHP '13: Pragmatic API Development
The Art of API Design - PHP Tek 2025, Chris Tankersley
Создание API, которое полюбят разработчики. Глубокое погружение
The Power of Open Data
2012 03 27_philly_jug_rewrite_static
PHP Server side restful API - linkedin
Restful design at work v2.0
API Best Practices
BeJUG JAX-RS Event
What’s Your Problem?
REST in ( a mobile ) peace @ WHYMCA 05-21-2011
So you think you know REST - DPC11
Profiling Web Archives IIPC GA 2015
Frans Rosén Keynote at BSides Ahmedabad
Ad

More from Phil Sturgeon (8)

PPT
PHP-FIG: Past, Present and Future
PDF
Become Master of Your Own Universe - DIBI 2013
PDF
Laravel and Composer
KEY
Why I &lt;3 Laravel 4
KEY
CodeIgniter 3.0
KEY
Cms expo
KEY
Introduction to Fuel
KEY
Running an Open-Source CodeIgniter project
PHP-FIG: Past, Present and Future
Become Master of Your Own Universe - DIBI 2013
Laravel and Composer
Why I &lt;3 Laravel 4
CodeIgniter 3.0
Cms expo
Introduction to Fuel
Running an Open-Source CodeIgniter project

Recently uploaded (20)

PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPT
Teaching material agriculture food technology
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Approach and Philosophy of On baking technology
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Empathic Computing: Creating Shared Understanding
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Machine learning based COVID-19 study performance prediction
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Encapsulation_ Review paper, used for researhc scholars
The Rise and Fall of 3GPP – Time for a Sabbatical?
20250228 LYD VKU AI Blended-Learning.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Teaching material agriculture food technology
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Approach and Philosophy of On baking technology
Advanced methodologies resolving dimensionality complications for autism neur...
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Digital-Transformation-Roadmap-for-Companies.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
NewMind AI Weekly Chronicles - August'25 Week I
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Empathic Computing: Creating Shared Understanding
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Machine learning based COVID-19 study performance prediction
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy

API Pain Points (PHPNE)

  • 1. A P I P A 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 2 0 1 4
  • 4. A R C H I T E C T U R E O L D S C H O O L
  • 7. D A T A 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
  • 8. E N D P O I N T T H E O R Y N A M I N G T H I N G S I S H A R D
  • 9. 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
  • 10. 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
  • 11. 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
  • 12. 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
  • 13. N O N E E D F O R S E O Q U E R Y S T R I N G S A R E F I N E /users/active/true /users?active=true
  • 14. 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
  • 15. 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 ZackKitzmillerTiny('lDpuU74QNH6B'); echo $tiny->to(5); // E echo $tiny->from('E'); // 5
  • 16. 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 RhumsaaUuidUuid; use RhumsaaUuidExceptio $uuid4 = Uuid::uuid4(); echo $uuid4; // 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a github.com/ramsey/uuid
  • 17. H T T P V E R B S M A T T E R H O N E S T L Y Dont be @jamiehannaford. That sounds like a bad day.
  • 18. F O R M P A Y 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=true18
  • 19. H A C K Y P A Y L O A D S N O T L I K E T H A T
  • 20. R E A L J S O N P A Y L O A D S T H N X !
  • 21. R E A D I N G R E A L D A T A I S E A S Y T H E H T T P W A Y json_decode($_POST['stupid-json']); json_decode(file_get_contents(‘php://input')); Input::get(‘foo’);
  • 23. 2 0 0 I S N O T T H E O N L Y 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!!'); }
  • 24. 2xx is all about success 3xx is all about redirection 4xx is all about client errors 5xx is all about service errors
  • 25. 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
  • 26. 418 - I am a Teapot http://httpstatus.es/418
  • 27. 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." } }
  • 28. 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
  • 29. 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 138 } }
  • 30. 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 } }
  • 31. 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“ } }
  • 32. O A U T H 2 . 0 thephpleague.com github.com/thephpleague/oauth2-server
  • 33. O A U T H 2 C A N D O A L O T P A 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 …
  • 34. U S E S S L
  • 35. L O L E X C E P T F O R …
  • 36. F A C E B O O K … Y O U B # % @ * D S ! ! ! S E R I O U S L Y Refresh Tokens? Lol
  • 37. 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 L Y Refresh Tokens? Kinda
  • 38. P R E S E N T A T I O N L A Y 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 T A I N
  • 39. return Places::all(); P R E S E N T A T I O N L A Y 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 T A I N
  • 42. 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
  • 43. 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
  • 44. P A G I N A T E D A T A G R O W S F A S T { "data": [ ... ], "cursors": { "after": "MTI=", "next_url": "https://api.example.com/places ?cursor=MTI%3" } }
  • 45. D E F I N E A L I M I T R A N G E P A G I N A T I O N D D O S if ($limit < 1 || $limit > 100) { $limit = 100; }
  • 46. A U T O M A T 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/
  • 47. P H P U N I T + B E H A T http://www.bil-jac.com/bestfriendsclub.php
  • 48. 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 """
  • 49. Scenario: Try to find an ` checkin When I request "GET /checkins/nope" Then I get a "404" response
  • 50. 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
  • 53. 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
  • 54. 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
  • 55. 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
  • 56. 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
  • 57. 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
  • 58. E V E R Y 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