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
Slide 17
Slide 17 text
Example of error
Status: 400
Content-Type: application/json; charset=UTF-8
{
"error": {
"code": 1001,
"message": "Price must be greater than 0."
}
}
17
Slide 18
Slide 18 text
Testing
Simpler than you think
Slide 19
Slide 19 text
HTTP
• Use Guzzle or built-in framework tool
• Generate HTTP request , compare output
19
Slide 20
Slide 20 text
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
Testing tips
• Create separate database for tests
• Write tests before you code:
• TDD
• Contract between you and client dev
22
Slide 23
Slide 23 text
Authentication
Nooo, I hate that part! Someone else code it plz.
Slide 24
Slide 24 text
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
Slide 25
Slide 25 text
OAuth2
• SSL required (can be risky)
• Advanced features like access scope
• Can be overkill if you need basic features
• Private credentials
25
Slide 26
Slide 26 text
OAuth2 - conceptual diagram
26
User Client app
(php/js/mobile)
API
Request Forward
Validate
Create
token
Store
token
Login form
Login
token
user/pass
Slide 27
Slide 27 text
Digest
• Its own encryption
• Easy to implement
• No replay (nonce)
• Comes out-of-the-box with some frameworks
27
Refactoring to API
Don't rewrite all the legacy at once
Slide 30
Slide 30 text
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
Slide 31
Slide 31 text
Implementation tips
Is this a good way to code it?
Slide 32
Slide 32 text
Libraries
• I use Symfony & Doctrine
• Aside from frameworks, I prefer small tools that don't do
too much magic
32
Slide 33
Slide 33 text
Reuse & standardize
• Goal: streamline endpoint creation
• Base controller for common request processing
• Base repository for querying with filters
• Keep things fully customizable
33
Slide 34
Slide 34 text
Performance
Make things faster. Much faster.
Slide 35
Slide 35 text
Benchmark
• Give Tideways or Blackfire a spin
• Make performance part of your test suite
• In dev/test mode, use a meta block
35
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
Slide 38
Slide 38 text
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
Slide 39
Slide 39 text
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
Slide 40
Slide 40 text
Anna Filina
• Development: PHP, JS, etc.
• Fix problems: bugs, performance, etc.
• Workshops: testing, Symfony, AngularJS, API, etc.
• Advisor: testing strategy, legacy code, etc.
40