API Pain Points (PHPNE)
-
Upload
phil-sturgeon -
Category
Technology
-
view
902 -
download
2
description
Transcript of API Pain Points (PHPNE)
A P I PA I N - P O I N T SGE TT I NG T H INGS W R O NG F O R F U N A ND PR O F I T
@P H ILST U R GE O N 2014
A RC H I T E C T U R EO LD SCH O O L
http://girlsgotsole.com/blog/thankful-thursday-rest-days/
DATA B A S E S E E D I N GLE AV E YO U R CU ST O ME R S A LO NE
E N D P O I N T T H E O RYNA MING T H I NGS I S H A R D
P LU RA L V S I N G U L A R ?CO NS IST E NCY I S K ING
/user/23
/users
P LU RA L V S I N G U L A R ?CO NS IST E NCY I S K ING
/opportunity/43
/opportunities
P LU RA L V S I N G U L A R ?CO NS IST E NCY I S K ING
/person/dave
/people
P LU RA L V S I N G U L A R ?CO NS IST E NCY I S K ING
/places/places/12/places/12/checkins/places/12/checkins/34/checkins/34
N O N E E D F O R S E OQ U E RY ST R I NGS A R E F I NE
/users/active/true
/users?active=true
A U T O - I N C R E M E N T = B A D
CT R L + S YO U R W E BS IT 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
CT R L + S YO U R W E BS IT E
github.com/zackkitzmiller/tiny-php
$tiny = new \ZackKitzmiller\Tiny('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
CT R L + S YO U R W E BS IT E
use Rhumsaa\Uuid\Uuid;use Rhumsaa\Uuid\Exceptio
$uuid4 = Uuid::uuid4();
echo $uuid4;// 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a
github.com/ramsey/uuid
H TT P V E R BS M ATT E RH O NE ST LY
Dont be @jamiehannaford. That sounds like a bad day.
F O R M PAY LOA D SJ U ST SE ND J SO N
foo=something&bar[baz]=thing&bar[stuff]=junk&bar=true
H AC KY PAY LOA D SNO T L IKE T H AT
R E A L J S O N PAY LOA D ST H NX!
R E A D I N G R E A L DATA I S E A S Y
T H E H TT P WAY
json_decode($_POST['stupid-json']);
json_decode(file_get_contents(‘php://input'));
Input::get(‘foo’);
200 I S NOT THE ON LY S UC C ES S
KNO W YO U R CO DE S
if ($statusCode != 200) {throw new Exception('AAGHH!!');
}
2xx is all about success3xx is all about redirection
4xx is all about client errors5xx 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 Teapothttp://httpstatus.es/418
C L E A R , H U M A N E R R O R S
W H AT H A PPE NE D
{ "error": { "errors": [ { "domain": "youtube.parameter", "reason": "missingRequiredParameter", "message": "No filter selected.", "locationType": "parameter", "location": "" } ], "code": 400, "message": "No filter selected." }}
E R R OR S S H OUL D MA K E S E N S E
W H AT H A PPE NE D
&mine=true
"reason": "missingRequiredParameter", "message": "No filter selected.",
…
WTF
S U PPL E M E N T H TT P C O D E S
W H AT H A PPE NE D
{"error": {
"type": "OAuthException", "message": "Session has expired at unix time 1385243766. The current unix time is 1385848532"}
}
S U PPL E M E N T H TT P C O D E S
W H AT H A PPE NE D
{ "error": { "message": "(#210) Subject must be a page.", "type": "OAuthException", "code": 210 }}
S U PPL E M E N T H TT P C O D E S
W H AT H A PPE NE D
{ "error": { "message": "(#210) Subject must be a page.", "type": "OAuthException", "code": 210, "url": “http://developers.facebook.com/errors#210“ }}
OA U T H 2 . 0
thephpleague.com
github.com/thephpleague/oauth2-server
OA U T H 2 C AN D O A LO T
PA SSW O R DS , I MPL IC I T , SO C IA L LO G INS…
U S E S S L
LO LE XCE PT F O R …
FAC E BOOK … YOU B#% @*DS ! ! !
SE R IO U SLY
Refresh Tokens?
Lol
YO U T U B E … YO U S E M I -B #% @ * D S ! ! !
ST I LL SE R IO U SLY
Refresh Tokens?
Kinda
P R E S E N TAT I O N L AY E RDO NT LE T U SE R S BE H IND T H E CU RTA IN
return Places::all();
P R E S E N TAT I O N L AY E RDO NT LE T U SE R S BE H IND T H E CU RTA IN
T RA N SFORM E RS… A SSE 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 SST O P YO U R I P H O NE DE V CO MP L A IN I NG
GET /checkins/dsfXte ?include=place,user,activity
PAG I N AT EDATA GR O W S FA ST
{"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 RA N G EPAG INAT IO N DDO S
if ($limit < 1 || $limit > 100) {$limit = 100;
}
A U T O M AT E T E S T I N GIF YOU LOVE YOUR JOB
http://www.engineersgotblued.com/
P H P U N I T + B E H AT
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 ` checkinWhen I request "GET /checkins/nope"Then I get a "404" response
Scenario:Wrong Arguments for user followGiven I have the payload:
""" {"is_following": "foo"} """
When I request "PUT /users/1”Then I get a "400" response
Not a boolean
apiblueprint.org
V E R S I O N I N G/ V 1 /DO E SNT CO U NT
https://api.example.com/v1/places
V E R S I O N I N G/ V 1 /DO E SNT CO U NT
https://api-v1.example.com/places
V E R S I O N I N G/ V 1 /DO E SNT CO U NT
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 /DO E SNT CO U NT
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 /DO E SNT CO U NT
Copy Facebook
Maybe?
THIS ONE TIME!
Facebook ruined the one good thing they ever did
E V E RY T H I N G I S W R O N GDO NT BE T H AT GU Y
troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html
leanpub.com/build-apis-you-wont-hate/c/TOONARMY