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

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

Jeremy Lindblom

July 29, 2016
Tweet

More Decks by Jeremy Lindblom

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. APIS Micro
    services
    Cloud
    REST
    Saas

    View Slide

  4. CLIENT
    SERVER

    View Slide

  5. View Slide

  6. $method = ?;
    $endpoint = ?;
    $payload = ?;
    $status = ?;
    $app->{$method}($endpoint, function () {
    /* The “easy” part */
    return response($payload, $status)
    });

    View Slide

  7. Time to make
    some design
    decisions!

    View Slide

  8. api.mygradebook.local
    × Create an assignment
    × Read assignments (single & multiple)
    × Update an assignment
    × Delete an assignment

    View Slide

  9. What Should the
    ENdpoints look like
    and Which HTTP
    Methods will we use?

    View Slide

  10. GET
    PUt
    Delete
    Options
    POST
    Patch
    Head
    Common HTTP Methods

    View Slide

  11. GET
    PUt (replace or create)
    Delete
    Options
    POST (create/other)
    Patch (update)
    Head
    Common HTTP Methods

    View Slide

  12. api.mygradebook.local
    POST /assignments - Create
    GET /assignments - List/Search
    GET /assignments/{id} – Read
    PATCH /assignments/{id} - Update
    DELETE /assignments/{id} - Delete

    View Slide

  13. https://leanpub.com/restful-api-design
    By:
    Keith Casey
    James Higginbotham
    Mailing List:
    “API Developer Weekly”

    View Slide

  14. Status Codes?

    View Slide

  15. 503

    View Slide

  16. 503
    SERVICE
    UNAVAILABLE

    View Slide

  17. 201

    View Slide

  18. 201
    CREATED

    View Slide

  19. 429

    View Slide

  20. 429
    TOO MANY
    REQUESTS

    View Slide

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

    View Slide

  22. URL

    View Slide

  23. HEADERS

    View Slide

  24. ELEPHPANT

    View Slide

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

    View Slide

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

    View Slide

  27. AUTH?

    View Slide

  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

    View Slide

  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

    View Slide

  30. https://github.com/dingo/api

    View Slide

  31. Dingo API
    × Content negotiation
    × Authentication adapters (inc. JWT & OAuth 2)
    × API versioning (in the headers)
    × Rate limiting middleware
    × Response builder/transformers

    View Slide

  32. Opinionated Content-type
    API_STANDARDS_TREE API_NAME API_VERSION
    Accept: application/vnd.mygradebook.v1+json

    View Slide

  33. Versioned ROUTING
    $api = app('Dingo\Api\Routing\Router');
    $api->version('v1', [], function ($api) {
    $api->get('/assignments', ...);
    $api->post('/assignments', ...);
    $api->patch('/assignments/{id}', ...);
    });

    View Slide

  34. RESPONSE BUILDERS + FRACTAL
    public function index() {
    $assgs = Assignment::all();
    return $this->response
    ->collection($assgs, new AssgTransformer)
    ->withHeader('X-MyGB-Count', count($assgs));
    }

    View Slide

  35. http://fractal.thephpleague.com/

    View Slide

  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();
    });

    View Slide

  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),
    ];
    }
    }

    View Slide

  38. TRANSFORMED JSON RESULT
    {
    'data': {
    'id': 'c3ecf466-c7ce-4df1-b6dd-6ad74937e626',
    'name': 'Reducing Fractions HW03',
    'pointsPossible': 20,
    'dueDate': '9/23/2016'
    }
    }

    View Slide

  39. https://github.com/ramsey/uuid

    View Slide

  40. DINGO Starter Project
    Lumen + Dingo + JWT Auth + CORS
    https://github.com/0plus1/lumendingojwtapi

    View Slide

  41. View Slide

  42. Let’s Consume
    our API!

    View Slide

  43. HTTP CLients
    × file_get_contents (and stream contexts)
    × cURL
    × HTTP extension
    × Libraries: Buzz, Requests, Guzzle

    View Slide

  44. https://github.com/guzzle/guzzle

    View Slide

  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+ )

    View Slide

  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',
    ]
    ]);

    View Slide

  47. POSTING aN ASSIGNMENT
    $response = $client->post('assignments', [
    'form_params' => [
    'name' => 'Reducing Fractions HW03',
    'pointsPossible' => 20,
    'dueDate' => '2016-09-23'
    ]
    ]);
    echo $response->getStatusCode();
    //> 201

    View Slide

  48. View Slide

  49. CLIENT
    SERVER

    View Slide

  50. CLIENT
    SERVER

    View Slide

  51. http://swagger.io/

    View Slide

  52. Swagger
    × Representation of your RESTful API
    × JSON or YAML
    × Large ecosystem
    × Documentation generation
    × Code generation
    × Gateway integration (e.g., Amazon API Gateway)

    View Slide

  53. However,
    Swagger has
    a new name...

    View Slide

  54. https://openapis.org/

    View Slide

  55. View Slide

  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"],
    ...

    View Slide

  57. SWAGGER DOCS (Part 2 - PATHS)
    "paths": {
    "/": {
    "get": {
    "parameters": [...]
    "responses": {...}
    }
    "post": {...},
    ...
    }
    }

    View Slide

  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
    },
    ...

    View Slide

  59. SWAGGER DOCS (Part 4 - RESPONSES)
    "200": {
    "description": "List all pets",
    "schema": {
    "title": "Pets",
    "type": "array",
    "items": {"$ref": "#/definitions/Pet"}
    }
    },
    ...

    View Slide

  60. SWAGGER DOCS (Part 5 - Definitions)
    "Pet": {
    "type": "object",
    "properties": {
    "name": {"type": "string"},
    "birthday": {"type": "integer", "format": "int32"}
    }
    },
    ...

    View Slide

  61. View Slide

  62. https://www.npmjs.com/package/bootprint

    View Slide

  63. INstalling & USING Bootprint
    > npm install -g bootprint
    > npm install -g bootprint-openapi
    > bootprint openapi ./swagger.json ./docs

    View Slide

  64. View Slide

  65. CLIENT
    SERVER

    View Slide

  66. Generate Swagger FROM CODE
    × Annotate your code for Swagger
    × https://github.com/zircote/swagger-php
    > swagger app -o public/swagger.json

    View Slide

  67. AnNotations
    /**
    * @SWG\Post(
    * path="/assignments",
    * operationId="createAssignment",
    * summary="Create an assignment.",
    * <<< PARAMETERS >>>
    * @SWG\Response(
    * response=201
    * )
    * )
    */
    public function create(Request $request) {...}

    View Slide

  68. AnNotations
    /**
    * ...
    * @SWG\Parameter(
    * name="name",
    * in="formData",
    * description="Name of the assignment.",
    * required=true,
    * type="string"
    * ),
    * ...
    */

    View Slide

  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)

    View Slide

  70. View Slide

  71. USING My Swagger-lite Guzzle Client
    $response = $client->createAssignment([
    'name' => 'Reducing Fractions HW03',
    'pointsPossible' => 20,
    'dueDate' => '2016-09-23'
    ]);
    echo $response->getStatusCode();
    //> 201

    View Slide

  72. APIS with Lumen, DINGO
    FRACTAL, UUID, Guzzle,
    OPENAPI (swagger),
    BootPrint, & More

    View Slide

  73. WHAT’s
    MISSING?

    View Slide

  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

    View Slide

  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/

    View Slide

  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

    View Slide

  77. THANK YOU!
    I’m Jeremy. See ya online!
    @jeremeamia • @phpbard
    @pnwphp • @azphp

    View Slide