Upgrade to Pro — share decks privately, control downloads, hide ads and more …

API Tips from the Frontline

API Tips from the Frontline

Anna Filina

June 09, 2015
Tweet

More Decks by Anna Filina

Other Decks in Programming

Transcript

  1. What you will learn • Don't repeat my mistakes •

    Overcome common obstacles • Build elegant & pragmatic APIs 3
  2. Response example: list { "data": [ {"name": "Skyrim"}, {"name": "Civilization

    V"} ], "page": { "number": 1, "size": 2, "pages": 50, "total": 100 } } 7
  3. Write • POST /products • PUT or PATCH /products/1 •

    DELETE /products/1 • Version your APIs: api.example.org/v1/products 8
  4. Multiple formats • xml, json, etc. • Can use 1

    endpoint with Accept header • Can send version, pagination & language info using headers too 10
  5. 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
  6. 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
  7. Plupload var uploader = new plupload.Uploader({ runtimes: 'html5,html4', max_file_size: '5mb',

    url: '/api/upload', filters: [{extensions: 'jpg,png,jpeg'}] }); uploader.init(); 14
  8. 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
  9. 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
  10. Example of error Status: 400 Content-Type: application/json; charset=UTF-8 { "error":

    { "code": 1001, "message": "Price must be greater than 0." } } 17
  11. 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
  12. Testing tips • Create separate database for tests • Write

    tests before you code: • TDD • Contract between you and client dev 22
  13. 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
  14. OAuth2 • SSL required (can be risky) • Advanced features

    like access scope • Can be overkill if you need basic features • Private credentials 25
  15. OAuth2 - conceptual diagram 26 User Client app
 (php/js/mobile) API

    Request Forward Validate Create token Store token Login form Login token user/pass
  16. Digest • Its own encryption • Easy to implement •

    No replay (nonce) • Comes out-of-the-box with some frameworks 27
  17. 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
  18. Libraries • I use Symfony & Doctrine • Aside from

    frameworks, I prefer small tools that don't do too much magic 32
  19. Reuse & standardize • Goal: streamline endpoint creation • Base

    controller for common request processing • Base repository for querying with filters • Keep things fully customizable 33
  20. Benchmark • Give Tideways or Blackfire a spin • Make

    performance part of your test suite • In dev/test mode, use a meta block 35
  21. 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
  22. 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
  23. 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
  24. Anna Filina • Development: PHP, JS, etc. • Fix problems:

    bugs, performance, etc. • Workshops: testing, Symfony, AngularJS, API, etc. • Advisor: testing strategy, legacy code, etc. 40