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
520
API Tips from the Frontline
Anna Filina
June 09, 2015
Tweet
Share
More Decks by Anna Filina
See All by Anna Filina
Upgrading Legacy to the Latest PHP Version
afilina
1
83
Better Code Design in PHP
afilina
0
230
Semi-Automated Refactoring and Upgrades with Rector
afilina
0
140
Better Code Design in PHP
afilina
1
410
Better Code Design in PHP
afilina
0
540
Adding Tests to Untestable Legacy Code
afilina
0
350
Upgrading Legacy to the Latest PHP Version
afilina
0
360
Semi-Automated Refactoring and Upgrades with Rector
afilina
0
250
Better Code Design in PHP
afilina
1
730
Other Decks in Programming
See All in Programming
Deep Dive into ~/.claude/projects
hiragram
8
1.5k
ruby.wasmで多人数リアルタイム通信ゲームを作ろう
lnit
2
270
VS Code Update for GitHub Copilot
74th
1
390
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
260
PHPで始める振る舞い駆動開発(Behaviour-Driven Development)
ohmori_yusuke
2
190
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
250
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
290
Railsアプリケーションと パフォーマンスチューニング ー 秒間5万リクエストの モバイルオーダーシステムを支える事例 ー Rubyセミナー 大阪
falcon8823
4
950
イベントストーミング図からコードへの変換手順 / Procedure for Converting Event Storming Diagrams to Code
nrslib
1
400
Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング
naoya
17
4.9k
都市をデータで見るってこういうこと PLATEAU属性情報入門
nokonoko1203
1
570
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
190
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Typedesign – Prime Four
hannesfritz
42
2.7k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
281
13k
How STYLIGHT went responsive
nonsquared
100
5.6k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.6k
Balancing Empowerment & Direction
lara
1
370
Testing 201, or: Great Expectations
jmmastey
42
7.5k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
The World Runs on Bad Software
bkeepers
PRO
69
11k
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