Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
API Tips from the Frontline
Search
Anna Filina
June 09, 2015
Programming
2
510
API Tips from the Frontline
Anna Filina
June 09, 2015
Tweet
Share
More Decks by Anna Filina
See All by Anna Filina
Better Code Design in PHP
afilina
0
210
Semi-Automated Refactoring and Upgrades with Rector
afilina
0
120
Better Code Design in PHP
afilina
0
320
Better Code Design in PHP
afilina
0
500
Adding Tests to Untestable Legacy Code
afilina
0
330
Upgrading Legacy to the Latest PHP Version
afilina
0
340
Semi-Automated Refactoring and Upgrades with Rector
afilina
0
230
Better Code Design in PHP
afilina
1
700
Effortless Software Development
afilina
1
300
Other Decks in Programming
See All in Programming
バックエンドNode.js × フロントエンドDeno で開発して得られた知見
ayame113
5
1.2k
‘무차별 LGTM~👍’만 외치던 우리가 ‘고봉밥 코드 리뷰’를?
hannah0731
0
520
CQRS+ES勉強会#1
rechellatek
0
380
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
190
いまさら聞けない生成AI入門: 「生成AIを高速キャッチアップ」
soh9834
11
3.4k
보일러플레이트 코드가 진짜 나쁜 건가요?
gaeun5744
0
360
フロントエンドテストの育て方
quramy
8
2.3k
PHPのガベージコレクションを深掘りしよう
rinchoku
0
240
Kubernetesで実現できるPlatform Engineering の現在地
nwiizo
2
1.6k
Coding Experience Cpp vs Csharp - meetup app osaka@9
harukasao
0
100
コンテナでLambdaをデプロイするときに知っておきたかったこと
_takahash
0
130
AIエージェントを活用したアプリ開発手法の模索
kumamotone
1
740
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
30k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
22
2.6k
A Tale of Four Properties
chriscoyier
158
23k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.4k
Statistics for Hackers
jakevdp
797
220k
The Invisible Side of Design
smashingmag
299
50k
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.6k
The Cost Of JavaScript in 2023
addyosmani
48
7.6k
Gamification - CAS2011
davidbonilla
80
5.2k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
14
1.1k
Transcript
foolab.ca | @foolabca API Tips From the Frontline BEPHPUG, Berlin
- June 9, 2015
Anna Filina • Developer • Problem solver • Teacher •
Advisor • FooLab + ConFoo 2
What you will learn • Don't repeat my mistakes •
Overcome common obstacles • Build elegant & pragmatic APIs 3
Endpoints What URL to call when
Lists • /products • /products?category=games,movies&lang=fr • /products?include=platforms • /products?sort=-date •
/products?page[number]=2&page[size]=100 • /products?lang=fr 5
Details • /products/1 • /products/1?include=photos,reviews 6
Response example: list { "data": [ {"name": "Skyrim"}, {"name": "Civilization
V"} ], "page": { "number": 1, "size": 2, "pages": 50, "total": 100 } } 7
Write • POST /products • PUT or PATCH /products/1 •
DELETE /products/1 • Version your APIs: api.example.org/v1/products 8
Request/Response How to format stuff
Multiple formats • xml, json, etc. • Can use 1
endpoint with Accept header • Can send version, pagination & language info using headers too 10
Request • Bad: Content-Type: application/x-www-form-urlencoded • Content-Type: application/json • Send
content (POST) in body, not headers 11
Request example: add POST /products HTTP/1.1 Host: api.example.org Content-Type: application/json;
charset=UTF-8 { "data": { "name": "Skyrim", "price": 19.99 } } 12
Upload • Use tools, don't DIY (do it yourself). •
Client-side: Symfony • Client-side (more dynamic): Plupload • Step 1: upload temp file. • Step 2: give file path to next API request. • Server-side: Guzzle. 13
Plupload var uploader = new plupload.Uploader({ runtimes: 'html5,html4', max_file_size: '5mb',
url: '/api/upload', filters: [{extensions: 'jpg,png,jpeg'}] }); uploader.init(); 14
Guzzle <? $url = 'http://example.org/profiles/1/edit'; $request = $client->createRequest('PATCH', $url); $reqBody
= $request->getBody(); $reqBody->setField('data', ['first_name':'Anna']); $file = new PostFile('i.jpg', fopen('/path', 'r')); $reqBody->addFile($file); $response = $client->send($request); 15
Status codes • Don't confuse API & HTTP codes •
2xx success • 3xx redirect • 4xx client error • 5xx server error • Send API-specific code in body 16
Example of error Status: 400 Content-Type: application/json; charset=UTF-8 { "error":
{ "code": 1001, "message": "Price must be greater than 0." } } 17
Testing Simpler than you think
HTTP • Use Guzzle or built-in framework tool • Generate
HTTP request , compare output 19
Guzzle test // tests/ApiProductTest.php public function testGetOneProduct() { $client =
new Client(); $response = $client->get('http://example.org/products/1', [ 'exceptions' => false, 'headers' => ['Accept' => 'application/json'] ]); $this->assertEquals(200, $response->getStatusCode()); // ... } 20
Guzzle test // ... $body = $response->getBody()->getContents(); $this->assertJsonStringEqualsJsonString('{ "data": {
"id": "1", "name": "Skyrim", "price": 19.99 } }', $body); 21
Testing tips • Create separate database for tests • Write
tests before you code: • TDD • Contract between you and client dev 22
Authentication Nooo, I hate that part! Someone else code it
plz.
Multiple methods • Don't send username/password in each request ◦
Especially with untrusted 3rd parties ◦ Especially if no SSL • You can have multiple auth methods for one API • Sessions similar to tokens 24
OAuth2 • SSL required (can be risky) • Advanced features
like access scope • Can be overkill if you need basic features • Private credentials 25
OAuth2 - conceptual diagram 26 User Client app (php/js/mobile) API
Request Forward Validate Create token Store token Login form Login token user/pass
Digest • Its own encryption • Easy to implement •
No replay (nonce) • Comes out-of-the-box with some frameworks 27
Digest - conceptual diagram 28 Request User/client app API Unauthorized
Validate digest (nonce,pass) Request nonce
Refactoring to API Don't rewrite all the legacy at once
Progressive rewrite • Rewrite one component at a time •
Start with whatever has fewer dependencies (or critical) • Delete dead code • Copy production data for dev environment 30
Implementation tips Is this a good way to code it?
Libraries • I use Symfony & Doctrine • Aside from
frameworks, I prefer small tools that don't do too much magic 32
Reuse & standardize • Goal: streamline endpoint creation • Base
controller for common request processing • Base repository for querying with filters • Keep things fully customizable 33
Performance Make things faster. Much faster.
Benchmark • Give Tideways or Blackfire a spin • Make
performance part of your test suite • In dev/test mode, use a meta block 35
Example { "meta": { "perf": { "db_time": 0.00367, "total_time": 0.3120,
"memory": 19661 } } } 36
Performance tips • Don't use lazy loading. Example: $product->getPhotos(). •
Craft your own joins and carefully select fields. • Avoid ORM built-in hydration for read operations. 37
Performance tips • Use API keys even for public endpoints
(DDoS mitigation). • Put stuff in Memcached/Redis (especially blocked keys). • HTTP server can check headers 38
Useful links • Standard API format http://jsonapi.org/format/ • Digest implementation
http://php.net/manual/en/features.http-auth.php • Symfony components http://symfony.com/doc/current/components/index.html • Book "Build APIs You Won't Hate" https://leanpub.com/build-apis-you-wont-hate 39
Anna Filina • Development: PHP, JS, etc. • Fix problems:
bugs, performance, etc. • Workshops: testing, Symfony, AngularJS, API, etc. • Advisor: testing strategy, legacy code, etc. 40
@afilina afilina.com