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
PRO
June 09, 2015
Programming
2
490
API Tips from the Frontline
Anna Filina
PRO
June 09, 2015
Tweet
Share
More Decks by Anna Filina
See All by Anna Filina
Semi-Automated Refactoring and Upgrades with Rector
afilina
PRO
0
68
Better Code Design in PHP
afilina
PRO
0
180
Better Code Design in PHP
afilina
PRO
0
440
Adding Tests to Untestable Legacy Code
afilina
PRO
0
290
Upgrading Legacy to the Latest PHP Version
afilina
PRO
0
300
Semi-Automated Refactoring and Upgrades with Rector
afilina
PRO
0
190
Better Code Design in PHP
afilina
PRO
1
650
Effortless Software Development
afilina
PRO
1
280
Writing Testable Symfony Apps
afilina
PRO
0
360
Other Decks in Programming
See All in Programming
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
110
macOS なしで iOS アプリを開発する(※ただし xxx に限る)
mitsuharu
1
180
TypeScript でバックもやるって実際どう? 実運用で困ったこと3選
yuichiro_serita
17
7.7k
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
2
440
14 Years of iOS: Lessons and Key Points
seyfoyun
1
760
暇に任せてProxmoxコンソール 作ってみました
karugamo
1
690
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
990
プロダクトの品質に コミットする / Commit to Product Quality
pekepek
2
760
これでLambdaが不要に?!Step FunctionsのJSONata対応について
iwatatomoya
2
3.5k
talk-with-local-llm-with-web-streams-api
kbaba1001
0
170
テスト自動化失敗から再挑戦しチームにオーナーシップを委譲した話/STAC2024 macho
ma_cho29
1
1.2k
The rollercoaster of releasing an Android, iOS, and macOS app with Kotlin Multiplatform | droidcon Italy
prof18
0
150
Featured
See All Featured
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
How to train your dragon (web standard)
notwaldorf
88
5.7k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
Side Projects
sachag
452
42k
4 Signs Your Business is Dying
shpigford
181
21k
The Cult of Friendly URLs
andyhume
78
6.1k
Building Applications with DynamoDB
mza
91
6.1k
The Language of Interfaces
destraynor
154
24k
Making the Leap to Tech Lead
cromwellryan
133
9k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
170
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
510
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