APIs with Lumen, Guzzle, & Swagger

APIs with Lumen, Guzzle, & Swagger

Building a quality RESTful API can be challenging. Let's discuss a few best practices and how embracing three particular technologies — the Lumen framework (and related packages), the Guzzle HTTP library, and the Swagger (OpenAPI) Specification — can make it easier for you to implement your API and for your users to consume your API. That way, everyone can spend more time adding business value, instead of writing boilerplate code. #laravel #php

Ca57a7cfac69ba3abf517470f3770aae?s=128

Jeremy Lindblom

July 29, 2016
Tweet

Transcript

  1. APIS With Lumen, Guzzle, & Swagger By Jeremy Lindblom (@jeremeamia)

  2. I’m Jeremy! Product Architect McGraw-Hill Education @jeremeamia • @phpbard @pnwphp

    • @azphp
  3. APIS Micro services Cloud REST Saas

  4. CLIENT SERVER

  5. None
  6. $method = ?; $endpoint = ?; $payload = ?; $status

    = ?; $app->{$method}($endpoint, function () { /* The “easy” part */ return response($payload, $status) });
  7. Time to make some design decisions!

  8. api.mygradebook.local × Create an assignment × Read assignments (single &

    multiple) × Update an assignment × Delete an assignment
  9. What Should the ENdpoints look like and Which HTTP Methods

    will we use?
  10. GET PUt Delete Options POST Patch Head Common HTTP Methods

  11. GET PUt (replace or create) Delete Options POST (create/other) Patch

    (update) Head Common HTTP Methods
  12. api.mygradebook.local POST /assignments - Create GET /assignments - List/Search GET

    /assignments/{id} – Read PATCH /assignments/{id} - Update DELETE /assignments/{id} - Delete
  13. https://leanpub.com/restful-api-design By: Keith Casey James Higginbotham Mailing List: “API Developer

    Weekly”
  14. Status Codes?

  15. 503

  16. 503 SERVICE UNAVAILABLE

  17. 201

  18. 201 CREATED

  19. 429

  20. 429 TOO MANY REQUESTS

  21. SHOULD the API Version go in the URL or in

    the HEaders?
  22. URL

  23. HEADERS

  24. ELEPHPANT

  25. application/json Or application/xml Or...

  26. HATEOAS? HAL • JSON-LD JSON-API • CUSTOM And More

  27. AUTH?

  28. API AUTH First Visit SSL? Later Visits Examples: ID +

    Secret YES ID + Secret HTTP Basic Auth ID + Secret YES ID + Token OAuth 2.0, JWT ID + Signature PLZ ID + Signature Signature V4, OAuth 1.0a
  29. APIS Are HARD! × REST & HTTP × API Versioning

    × Status Codes × Content Negotiation × HATEOAS × Auth × Streams / Blobs × Pagination × Idempotency × Rate Limiting × CORS × Response Caching × Scalability & Perf. × CAP Theorem
  30. https://github.com/dingo/api

  31. Dingo API × Content negotiation × Authentication adapters (inc. JWT

    & OAuth 2) × API versioning (in the headers) × Rate limiting middleware × Response builder/transformers
  32. Opinionated Content-type API_STANDARDS_TREE API_NAME API_VERSION Accept: application/vnd.mygradebook.v1+json

  33. Versioned ROUTING $api = app('Dingo\Api\Routing\Router'); $api->version('v1', [], function ($api) {

    $api->get('/assignments', ...); $api->post('/assignments', ...); $api->patch('/assignments/{id}', ...); });
  34. RESPONSE BUILDERS + FRACTAL public function index() { $assgs =

    Assignment::all(); return $this->response ->collection($assgs, new AssgTransformer) ->withHeader('X-MyGB-Count', count($assgs)); }
  35. http://fractal.thephpleague.com/

  36. Assignments Table Schema::create('assignments', function ($table) { $table->increments('id'); $table->uuid('external_id')->unique(); $table->string('name', 100);

    $table->integer('points'); $table->timestamp('due_date'); $table->timestamps(); });
  37. Assignment fractal transformer class AssgTransformer extends TransformerAbstract { public function

    transform(Assignment $assg) { return [ 'id' => $assg->external_id, 'name' => $assg->name, 'pointsPossible' => (int) $assg->points, 'dueDate' => date('n/j/Y', $assg->due_date), ]; } }
  38. TRANSFORMED JSON RESULT { 'data': { 'id': 'c3ecf466-c7ce-4df1-b6dd-6ad74937e626', 'name': 'Reducing

    Fractions HW03', 'pointsPossible': 20, 'dueDate': '9/23/2016' } }
  39. https://github.com/ramsey/uuid

  40. DINGO Starter Project Lumen + Dingo + JWT Auth +

    CORS https://github.com/0plus1/lumendingojwtapi
  41. None
  42. Let’s Consume our API!

  43. HTTP CLients × file_get_contents (and stream contexts) × cURL ×

    HTTP extension × Libraries: Buzz, Requests, Guzzle
  44. https://github.com/guzzle/guzzle

  45. Guzzle HTTP Client × HTTP Client for PHP × Wrapper

    for cURL (and other stuff) × PSR-7 compliant × Capable of concurrent & async requests × Popular Lib (5700+ , 32,000,000+ )
  46. Configuring Guzzle $client = new GuzzleHttp\Client([ 'base_uri' => 'https://api.mygradebook.local', 'auth'

    => ['Si39fSKkjqba459', 'dl2+aScKw/asjASD721'], 'headers' => [ 'Accept' => 'application/vnd.mygradebook.v1+json', ] ]);
  47. POSTING aN ASSIGNMENT $response = $client->post('assignments', [ 'form_params' => [

    'name' => 'Reducing Fractions HW03', 'pointsPossible' => 20, 'dueDate' => '2016-09-23' ] ]); echo $response->getStatusCode(); //> 201
  48. None
  49. CLIENT SERVER

  50. CLIENT SERVER

  51. http://swagger.io/

  52. Swagger × Representation of your RESTful API × JSON or

    YAML × Large ecosystem × Documentation generation × Code generation × Gateway integration (e.g., Amazon API Gateway)
  53. However, Swagger has a new name...

  54. https://openapis.org/

  55. None
  56. SWAGGER DOCS (Part 1 - Meta) { "swagger": "2.0", "info":

    {...}, "host": "petstore-api.herokuapp.com", "basePath": "/pet", "schemes": ["http", "https"], "consumes": ["application/json"], "produces": ["application/json"], ...
  57. SWAGGER DOCS (Part 2 - PATHS) "paths": { "/": {

    "get": { "parameters": [...] "responses": {...} } "post": {...}, ... } }
  58. SWAGGER DOCS (Part 3 - PARAMeters) { "name": "limit", "in":

    "query", (query, path, formData, headers, body) "description": "number of pets to return", "type": "integer", "default": 10, "maximum": 100 }, ...
  59. SWAGGER DOCS (Part 4 - RESPONSES) "200": { "description": "List

    all pets", "schema": { "title": "Pets", "type": "array", "items": {"$ref": "#/definitions/Pet"} } }, ...
  60. SWAGGER DOCS (Part 5 - Definitions) "Pet": { "type": "object",

    "properties": { "name": {"type": "string"}, "birthday": {"type": "integer", "format": "int32"} } }, ...
  61. None
  62. https://www.npmjs.com/package/bootprint

  63. INstalling & USING Bootprint > npm install -g bootprint >

    npm install -g bootprint-openapi > bootprint openapi ./swagger.json ./docs
  64. None
  65. CLIENT SERVER

  66. Generate Swagger FROM CODE × Annotate your code for Swagger

    × https://github.com/zircote/swagger-php > swagger app -o public/swagger.json
  67. AnNotations /** * @SWG\Post( * path="/assignments", * operationId="createAssignment", * summary="Create

    an assignment.", * <<< PARAMETERS >>> * @SWG\Response( * response=201 * ) * ) */ public function create(Request $request) {...}
  68. AnNotations /** * ... * @SWG\Parameter( * name="name", * in="formData",

    * description="Name of the assignment.", * required=true, * type="string" * ), * ... */
  69. Generate Code FROM SWAGGER × Swagger website has: × Client

    generation (decent cURL client) × Server generation (Lumen?) × jolicode/jane-openapi (pluggable client lib) × jl6m/swagger-lite (simple, Guzzle-based)
  70. None
  71. USING My Swagger-lite Guzzle Client $response = $client->createAssignment([ 'name' =>

    'Reducing Fractions HW03', 'pointsPossible' => 20, 'dueDate' => '2016-09-23' ]); echo $response->getStatusCode(); //> 201
  72. APIS with Lumen, DINGO FRACTAL, UUID, Guzzle, OPENAPI (swagger), BootPrint,

    & More
  73. WHAT’s MISSING?

  74. HOW Can You Help? × Publish a Swagger doc for

    your API × Adopt a Swagger tool or make a new one × Get involved in the OpenAPI group × Improve Lumen/Laravel’s API ecosystem
  75. Resources & CREDITS × laravel/lumen docs: https://lumen.laravel.com/docs/5.2 × dingo/api docs:

    https://github.com/dingo/api/wiki × jwt-auth docs: https://github.com/tymondesigns/jwt-auth/wiki × API starter project: https://github.com/0plus1/lumendingojwtapi × Slides template (Jachimo) from: http://www.slidescarnival.com/ × ramsey/uuid lib: https://github.com/ramsey/uuid × Guzzle docs: http://docs.guzzlephp.org/en/latest/ × Swagger website: http://swagger.io/ × OpenAPI Initiative website: https://openapis.org/
  76. Resources & CREDITS × UUIDs in Laravel: http://humaan.com/using-uuids-with-eloquent-in-laravel/ × Percona

    UUID: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ × UUID model traits: https://github.com/alsofronie/eloquent-uuid/tree/master/src × HAL library: https://github.com/blongden/hal × JSON-API library: https://github.com/neomerx/json-api × JSON-LD library: https://github.com/lanthaler/JsonLD × Guzzle OAuth 2 library: https://github.com/Sainsburys/guzzle-oauth2-plugin × API design book: https://leanpub.com/restful-api-design × Swagger-lite Guzzle client: https://github.com/jeremeamia/guzzle-swagger-lite × Bootprint: https://www.npmjs.com/package/bootprint × Swagger-PHP: https://github.com/zircote/swagger-php
  77. THANK YOU! I’m Jeremy. See ya online! @jeremeamia • @phpbard

    @pnwphp • @azphp