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

OSCON 2017 - Contract-First API Development Using the OpenAPI Specification (fka Swagger)

OSCON 2017 - Contract-First API Development Using the OpenAPI Specification (fka Swagger)

Dave Forgac

May 09, 2017
Tweet

More Decks by Dave Forgac

Other Decks in Technology

Transcript

  1. Contract-first API
    development
    using the OpenAPI Specification
    (fka Swagger)

    View full-size slide

  2. Ian Zelikman
    @izcoder
    Dave Forgac
    @tylerdave

    View full-size slide

  3. BetterAPIs.com
    https://github.com/tylerdave/OpenAPI-Tutorial/

    View full-size slide

  4. Updates
    Get repo updates
    git pull
    Reprovision VM
    vagrant suspend
    vagrant reload --provision
    Log in
    vagrant ssh

    View full-size slide

  5. Backup Plan
    http://editor.swagger.io/

    View full-size slide

  6. REST
    Standard

    View full-size slide

  7. REST
    Standard
    Architectural Style

    View full-size slide

  8. REST
    Standard
    Architectural Style
    HTTP w/ Constraints

    View full-size slide

  9. REST
    Standard
    Architectural Style
    HTTP w/ Constraints
    REST-inspired HTTP APIs

    View full-size slide

  10. API Contract

    View full-size slide

  11. API Contract
    Client ↔ Provider

    View full-size slide

  12. API Contract
    Client ↔ Provider
    Interface Specification

    View full-size slide

  13. API Contract
    Client ↔ Provider
    Interface Specification
    SLA, ToS, Limits, Pricing, etc.

    View full-size slide

  14. JSON
    JavaScript Object Notation

    View full-size slide

  15. JSON
    JavaScript Object Notation
    {
    "things": [
    "foo",
    "bar"
    ],
    "message": "Hello, World!"
    }

    View full-size slide

  16. JSON Schema
    {
    "title": "Example Schema",
    "type": "object",
    "properties": {
    "displayName": {
    "type": "string"
    },
    "age": {
    "description": "Age in years",
    "type": "integer",
    "minimum": 0
    }
    },
    "required": ["firstName", "lastName"]
    }

    View full-size slide

  17. YAML
    Serialization format

    View full-size slide

  18. YAML
    Serialization format
    (More) human-readable

    View full-size slide

  19. YAML
    Serialization format
    (More) human-readable
    Superset of JSON

    View full-size slide

  20. YAML
    Serialization format
    (More) human-readable
    Superset of JSON
    Language Support

    View full-size slide

  21. YAML Basics - Lists
    ---
    colors:
    - red
    - green
    - blue
    ...

    View full-size slide

  22. YAML Basics - Dictionaries
    ---
    session:
    title: Contract-First API Development
    type: tutorial
    ...

    View full-size slide

  23. YAML Basics - Spanning
    ---
    description: |
    This is a long description
    using a pipe
    which will preserve newlines.
    description2: >
    This is a long desciption using > which
    will ignore
    new
    lines.
    ...

    View full-size slide

  24. YAML Basics - Nesting
    ---
    session:
    name: Contract-First API Development
    type: tutorial
    topics:
    - apis
    - openapi specification
    - swagger
    languages: ['java', 'nodejs', 'python']
    description: >
    A really useful tutorial during which you'll
    learn about API specifications and stuff.
    ...

    View full-size slide

  25. JSON
    "Talk": {
    "type": "object",
    "properties": {
    "id": {
    "type": "integer"
    },
    "title": {
    "minLength": 1,
    "type": "string",
    "maxLength": 144
    }
    }
    }
    YAML
    Talk:
    type: object
    properties:
    id:
    type: integer
    title:
    type: string
    minLength: 1
    maxLength: 144
    Compare

    View full-size slide

  26. API Definitions

    View full-size slide

  27. API Definitions
    WSDL / WADL

    View full-size slide

  28. API Definitions
    WSDL / WADL
    Swagger -> OpenAPI Spec

    View full-size slide

  29. API Definitions
    WSDL / WADL
    Swagger -> OpenAPI Spec
    API Blueprint

    View full-size slide

  30. API Definitions
    WSDL / WADL
    Swagger -> OpenAPI Spec
    API Blueprint
    RAML

    View full-size slide

  31. OpenAPI Spec

    View full-size slide

  32. OpenAPI Spec
    Structure

    View full-size slide

  33. OpenAPI Spec
    Structure
    History

    View full-size slide

  34. OpenAPI Spec
    Structure
    History
    Future

    View full-size slide

  35. OpenAPI 3.0
    Coming Soon

    View full-size slide

  36. OpenAPI 3.0
    Coming Soon
    Tooling to Follow

    View full-size slide

  37. This Tutorial

    View full-size slide

  38. Goals
    OpenAPI Spec

    View full-size slide

  39. Goals
    OpenAPI Spec
    Testing

    View full-size slide

  40. Goals
    OpenAPI Spec
    Testing
    Mock

    View full-size slide

  41. Goals
    OpenAPI Spec
    Testing
    Mock
    Basic Implementation

    View full-size slide

  42. Goals
    OpenAPI Spec
    Testing
    Mock
    Basic Implementation
    Documentation

    View full-size slide

  43. Repo Layout
    ├── implementation
    │ └── ...
    ├── lessons
    │ ├── lesson-1.01
    │ │ ├── default_broken.yaml
    │ │ └── solution.yaml
    │ ├── lesson-1.02
    │ │ ├── example.json
    │ ... ...
    │ ├── lesson-2.01
    │ │ └── README.md
    │ └── ...
    ├── presentation
    │ └── ...
    └── work

    View full-size slide

  44. Synced Folder
    Repo dir on host
    mapped to
    /home/ubuntu/tutorial-repo/ on VM

    View full-size slide

  45. Lessons
    Instructions
    Work in work directory
    Via editor on host machine
    Or via editor in VM terminal
    Save betterapis.yml
    Run validator within VM:
    swagger validate tutorial-repo/work/betterapis.yml

    View full-size slide

  46. Lesson Solutions
    Done?
    Compare with contents of
    lessons/lesson-x.xx/solution.xxx
    Stuck?
    Copy lessons/lesson-x.xx/solution.xxx to work

    View full-size slide

  47. Lesson 1.01: Setup
    Goals
    Explore the environment.
    Look at some Open API example specs and
    exercise the tools we will use.

    View full-size slide

  48. Lesson 1.01: Setup
    Tooling
    Swagger editor:
    http://localhost:8000/
    Validator:
    swagger validate tutorial-repo/lessons/lesson-1.02/solution.yaml

    View full-size slide

  49. Lesson 1.01: Setup
    Exercise Instructions
    Load several examples from the swagger editor,
    review them.
    Import the broken examples from lesson-1.01
    directory. Try fixing the errors.

    View full-size slide

  50. Solution 1.01
    Notes
    Got familiar with basic OpenAPI Spec structure

    View full-size slide

  51. Lesson 1.02: Hello, World!
    Goals
    Building a first (basic) spec.

    View full-size slide

  52. YAML Example

    View full-size slide

  53. JSON Example

    View full-size slide

  54. Lesson 1.02: Hello, World!
    Exercise Instructions
    Build an API for a conference called betterapis
    Include metadata as shown in the example
    Paths are empty for now

    View full-size slide

  55. Solution 1.02
    Notes
    This solution might be a bit different than yours in
    regards to the metadata.
    Valid Spec!

    View full-size slide

  56. Lesson 1.03: Pets
    Goals
    Get familiar with defining paths.

    View full-size slide

  57. Lesson 1.03: Pets
    Basic Path
    /pets:
    get:
    summary: Get a list of pets
    description: Retrieve a list of pets
    responses:
    201:
    description: OK

    View full-size slide

  58. Lesson 1.03: Pets
    Exercise Instructions
    Add two paths to the API: /talks /speakers .
    Both paths only support GET and only return
    status code 200.

    View full-size slide

  59. Solution 1.03
    Notes
    We defined the very basic fields and objects
    needed for a valid path.

    View full-size slide

  60. Lesson 1.04: Registration
    Goals
    Learn to define complex operations on the API.

    View full-size slide

  61. Lesson 1.04: Registration
    Paths, Actions
    paths:
    /pets:
    post:
    summary: Add pet to DB
    description: Results in new pet information added to the DB
    parameters:
    - name: pet
    in: body
    description: Pet details
    schema:
    required: [name, status]
    properties:
    name:
    type: string
    description: The pet name

    View full-size slide

  62. Lesson 1.04: Registration
    Paths, Actions (contd.)
    responses:
    201:
    description: Created new pet in the database
    schema:
    required: [pet-id]
    properties:
    pet-id:
    type: number
    description: Unique Id for the pet in the system

    View full-size slide

  63. Lesson 1.04: Registration
    Exercise Instructions
    Add actions to support speaker registration and
    talk submission
    You are free to define the speaker and talk objects
    as you like as long as you define a unique id in
    both and exercise defining more than one basic
    type for the object properties.

    View full-size slide

  64. Solution 1.04
    Notes
    Additional properties: readOnly , format , pattern

    View full-size slide

  65. Lesson 1.05: The Minimalist API
    Goals
    Reusing definitions.
    Learn more in depth about action objects and
    request parameters.

    View full-size slide

  66. Lesson 1.05: The Minimalist API
    Path Parameter
    /pets/{pet-id}:
    parameters:
    pet-id:
    name: pet-id
    in: path
    description: Pet identifier
    type: number
    required: true

    View full-size slide

  67. Lesson 1.05: The Minimalist API
    Parameter Reuse
    /pets/{pet-id}:
    parameters:
    - $ref: '#/parameters/pet-id'
    ...
    parameters:
    pet-id:
    name: pet-id
    in: path
    description: Pet identifier
    type: number
    required: true

    View full-size slide

  68. Lesson 1.05: The Minimalist API
    Definitions Reuse
    ...
    schema:
    $ref: '#/definitions/Pet'
    ...
    definitions:
    Pet:
    type: object
    required: [name, status]
    properties:
    ...
    Pets:
    type: array
    items:
    $ref: "#/definitions/Pet"

    View full-size slide

  69. Lesson 1.05: The Minimalist API
    Exercise Instructions
    1. Refactor your API to use Talk and Speaker
    objects. Define Talks and Speakers objects based
    on the previous and update the responses from
    /speakers and /talks paths.
    2. Add a two new paths /speakers/{speaker-id} and
    /talks/{talk-id} . Define all the CRUD operations for
    them and use parameter definition outside of the
    action for path parameter.

    View full-size slide

  70. Solution 1.05
    Notes
    Time saving with definition. More readable.
    Example response in the solution

    View full-size slide

  71. Lesson 1.06: Responses
    Goals
    Learn more about parameter definition via
    pagination
    Learn How to define reusable responses
    Default responses

    View full-size slide

  72. Lesson 1.06: Responses
    Pagination
    parameters:
    - $ref: '#/parameters/page-size'
    - $ref: '#/parameters/page-number'
    ...
    parameters:
    page-size:
    name: page-size
    in: query
    description: Number of items
    type: integer
    format: int32
    minimum: 1
    maximum: 100
    multipleOf: 10
    default: 10

    View full-size slide

  73. Lesson 1.06: Responses
    Response Definition
    responses:
    ServerErrorResponse:
    description: Server error during request.
    schema:
    $ref: "#/definitions/Error"
    definitions:
    Error:
    properties:
    code:
    type: integer
    message:
    type: string

    View full-size slide

  74. Lesson 1.06: Responses
    Default Response
    /pets/{pet-id}/
    delete:
    responses:
    ...
    default:
    $ref: '#/responses/UnknownResponse'
    responses:
    UnknownResponse:
    description: This response is not yet documented by this API.

    View full-size slide

  75. Lesson 1.06: Responses
    Exercise Instructions
    Add pagination to the /talks and /speakers paths.
    Pagination should be included by at least two
    parameters: page-size , page-number .
    Add the following responses to all paths: 400, 500,
    default.

    View full-size slide

  76. Solution 1.06
    Notes
    Functionality complete API

    View full-size slide

  77. Lesson 1.07: Secure Your APIs
    Goals
    Learn the different security schemas supported.
    Global vs. local security via file upload definition
    example.

    View full-size slide

  78. Lesson 1.07: Secure Your APIs
    Basic Auth
    securityDefinitions:
    type: basic

    View full-size slide

  79. Lesson 1.07: Secure Your APIs
    API Key
    securityDefinitions:
    "type": "apiKey",
    "name": "api_key",
    "in": "header"

    View full-size slide

  80. Lesson 1.07: Secure Your APIs
    OAuth2
    securityDefinitions:
    OauthSecurity:
    type: oauth2
    flow: accessCode
    authorizationUrl: 'https://oauth.swagger.io.com/authorization'
    tokenUrl: 'https://oauth.swagger.io/token'
    scopes:
    admin: Admin scope
    user: User scope
    security:
    - OauthSecurity:
    - user

    View full-size slide

  81. Lesson 1.07: Secure Your APIs
    File Upload
    paths:
    /pets/{pet-id}/picture:
    parameters:
    - $ref: '#/parameters/pet-id'
    post:
    description: Admin operation to upload a pet picture
    operationId: UploadPicture
    security:
    - OauthSecurity:
    - admin
    consumes:
    - multipart/form-data
    parameters:
    - name: picture
    in: formData

    View full-size slide

  82. Lesson 1.07: Secure Your APIs
    Exercise Instructions
    Define a security scheme for your API. Use Oauth2.
    Add a new path to be able to upload speaker
    resume and secure it using admin role.

    View full-size slide

  83. Solution 1.07
    Notes
    Security representation in the editor
    Header in responses

    View full-size slide

  84. Lesson 1.08: Doc the Docs
    Goals
    Learn additional points on spec documentation

    View full-size slide

  85. Lesson 1.08: Doc the Docs
    OperationId
    /pets:
    get:
    operationId: GetPets

    View full-size slide

  86. Description GFM
    /pets:
    get:
    description: ## Retrieve multiple pet objects.
    For example:
    - pet1
    - pet2

    View full-size slide

  87. Lesson 1.08: Doc the Docs
    Tags
    paths:
    /pets:
    get:
    tags:
    - pet
    ...
    tags:
    name: pet
    description: Pet operations

    View full-size slide

  88. Lesson 1.08: Doc the Docs
    Exercise Instructions
    Update for API with more information on the
    operations description, using GFM.
    Add tags and operationIds to all your operations

    View full-size slide

  89. Solution 1.08
    Notes
    Tags in the editor

    View full-size slide

  90. Lesson 1.09: Can We Split This?
    Goals
    Learn how to support not having all the API in one
    flat file

    View full-size slide

  91. Lesson 1.09: Can We Split This?
    Reference External Files
    /pets:
    get:
    summary: Get a list of pets
    description: Retrieve a list of pets
    operationId: GetPets
    parameters:
    - $ref: 'parameters.yaml#/page-size'
    - $ref: 'parameters.yaml#/page-number'

    View full-size slide

  92. Lesson 1.09: Can We Split This?
    parameters.yaml
    Parameters:
    page-size:
    name: page-size
    in: query
    description: Number of items
    type: integer
    format: int32
    minimum: 1
    maximum: 100
    multipleOf: 10
    default: 10

    View full-size slide

  93. Lesson 1.09: Can We Split This?
    Serving External Files

    View full-size slide

  94. Lesson 1.09: Can We Split This?
    Exercise Instructions
    Split your API spec. The proposed scheme is to
    have separate file for definitions, parameters and
    responses. You can consider other split strategies.

    View full-size slide

  95. Solution 1.09
    Notes
    A better-organized specification

    View full-size slide

  96. Part 1 Recap
    1.01: Setup
    1.02: Hello, World!
    1.03: Pets
    1.04: Registration
    1.05: The Minimalist API
    1.06: Responses
    1.07: Secure Your APIs
    1.08: Doc the Docs
    1.09: Can We Split This?

    View full-size slide

  97. Contract-first API
    development
    using the OpenAPI Specification
    (fka Swagger)
    Part 2

    View full-size slide

  98. What do we get?

    View full-size slide

  99. What do we get?

    View full-size slide

  100. Benefits
    Documentation

    View full-size slide

  101. Benefits
    Documentation
    Mocking

    View full-size slide

  102. Benefits
    Documentation
    Mocking
    Testing

    View full-size slide

  103. Benefits
    Documentation
    Mocking
    Testing
    Code Generation

    View full-size slide

  104. Benefits
    Documentation
    Mocking
    Testing
    Code Generation

    View full-size slide

  105. Code Generation

    View full-size slide

  106. Code Generators

    View full-size slide

  107. Code Generators
    Servers

    View full-size slide

  108. Code Generators
    Servers
    Clients

    View full-size slide

  109. Code Generators
    Servers
    Clients
    Documentation

    View full-size slide

  110. Swagger-Codegen

    View full-size slide

  111. Swagger-Codegen
    Via Swagger editor
    Calls to https://generator.swagger.io/

    View full-size slide

  112. Swagger-Codegen
    Via Swagger editor
    Calls to https://generator.swagger.io/
    Via CLI
    http://swagger.io/swagger-codegen/

    View full-size slide

  113. Integrated
    Frameworks

    View full-size slide

  114. Integrated
    Frameworks
    Swagger Inflector (Java)

    View full-size slide

  115. Integrated
    Frameworks
    Swagger Inflector (Java)
    swagger-node (Node.js)

    View full-size slide

  116. Integrated
    Frameworks
    Swagger Inflector (Java)
    swagger-node (Node.js)
    Connexion (Python)

    View full-size slide

  117. Lesson 2.01: Code Generation
    Goals
    Server/Client Code from Spec

    View full-size slide

  118. Generate Server

    View full-size slide

  119. Generate Client

    View full-size slide

  120. Lesson 2.01: Code Generation
    Exercise Instructions
    Generate server & client side code with your
    favorite option provided by the code generator.
    (bonus) Update server side code so that the /talks
    and /speakers paths return empty list on GET. Use
    the methods provided by the client code in order
    test the responses from the server.

    View full-size slide

  121. Solution 2.01
    Notes
    Experimented with code generated

    View full-size slide

  122. Connexion
    Python + Flask

    View full-size slide

  123. Connexion
    Python + Flask
    Spec As Configuration

    View full-size slide

  124. Connexion
    Python + Flask
    Spec As Configuration
    Routing, Validation, etc.

    View full-size slide

  125. Connexion
    Python + Flask
    Spec As Configuration
    Routing, Validation, etc.

    View full-size slide

  126. Explicit Routing

    View full-size slide

  127. Explicit Routing
    Explicit Function Name
    paths:
    /hello_world:
    post:
    operationId: myapp.api.hello_world

    View full-size slide

  128. Explicit Routing
    Explicit Function Name
    paths:
    /hello_world:
    post:
    operationId: myapp.api.hello_world
    Separate Controller Name
    paths:
    /hello_world:
    post:
    x-swagger-router-controller: myapp.api
    operationId: hello_world

    View full-size slide

  129. Automatic Routing

    View full-size slide

  130. Automatic Routing
    from connexion.resolver import RestyResolver
    app = connexion.FlaskApp(__name__)
    app.add_api('swagger.yaml', resolver=RestyResolver('api'))

    View full-size slide

  131. Automatic Route Resolution
    paths:
    /:
    get:
    # Implied operationId: api.get
    /foo:
    get:
    # Implied operationId: api.foo.search
    post:
    # Implied operationId: api.foo.post
    '/foo/{id}':
    get:
    # Implied operationId: api.foo.get
    put:
    # Implied operationId: api.foo.put
    copy:
    # Implied operationId: api.foo.copy
    delete:
    # Implied operationId: api.foo.delete

    View full-size slide

  132. Request Validation

    View full-size slide

  133. Request Validation
    JSON Schema

    View full-size slide

  134. Request Validation
    JSON Schema
    Required parameters

    View full-size slide

  135. Request Validation
    JSON Schema
    Required parameters
    Types and Formats

    View full-size slide

  136. Request Validation
    JSON Schema
    Required parameters
    Types and Formats
    Custom Validators

    View full-size slide

  137. Request Validation
    JSON Schema
    Required parameters
    Types and Formats
    Custom Validators
    HTTP 400 w/ Details

    View full-size slide

  138. Response Handling

    View full-size slide

  139. Response Handling
    Serialization

    View full-size slide

  140. Response Handling
    Serialization
    JSON Encoder

    View full-size slide

  141. Response Handling
    Serialization
    JSON Encoder
    Validation Optional

    View full-size slide

  142. Response Handling
    Serialization
    JSON Encoder
    Validation Optional
    Custom Validators

    View full-size slide

  143. Security
    OAuth 2 via Spec

    View full-size slide

  144. Security
    OAuth 2 via Spec
    DIY
    API Key
    Basic Auth

    View full-size slide

  145. Other Features

    View full-size slide

  146. Other Features
    Swagger UI

    View full-size slide

  147. Other Features
    Swagger UI
    Swagger JSON

    View full-size slide

  148. Other Features
    Swagger UI
    Swagger JSON
    Flask Integration

    View full-size slide

  149. Other Features
    Swagger UI
    Swagger JSON
    Flask Integration

    View full-size slide

  150. Lesson 2.02: Run the API
    Goals
    Python/Flask
    Connexion

    View full-size slide

  151. Connexion
    Implementation

    View full-size slide

  152. Lesson 2.02: Run the API
    Exercise Instructions
    Run the the betterapis application using the
    connexion implementation
    Activate virtualenv: workon tutorial
    Run app: python -m betterapis
    Register two speakers and submit a talk for each
    one.
    Use HTTP POSTs via Postman, curl, et al.
    Request speaker list to verify data persisted.

    View full-size slide

  153. Solution 2.02
    Notes
    Populated data

    View full-size slide

  154. Lesson 2.03: Mock Server
    Goals
    Run mock server for client to experiment with the
    API

    View full-size slide

  155. Lesson 2.03: Mock Server
    examples
    responses:
    200:
    description: Returns a specific talk
    schema:
    $ref: '#/definitions/Pet'
    examples:
    application/json:
    {
    id: 12345,
    name: "pythagoras",
    status: "Adopted"
    }

    View full-size slide

  156. Lesson 2.03: Mock Server
    Usage
    connexion run betterapis.yaml --mock=all -v

    View full-size slide

  157. Lesson 2.03: Mock Server
    Exercise Instructions
    Update responses to have examples
    Run and test your mock server

    View full-size slide

  158. Solution 2.03
    Notes
    Can mock with any spec

    View full-size slide

  159. Lesson 2.04: Test with Dredd
    Goals
    Learn how the spec connects tests and
    implementation

    View full-size slide

  160. Lesson 2.04: Test with Dredd
    Installation
    Using npm
    Provided in the VM

    View full-size slide

  161. Lesson 2.04: Test with Dredd
    Usage
    Dredd init
    ? Location of the API description document
    tutorial-repo/implementation/betterapis/specs/betterapis.yaml
    ? Command to start API backend server e.g. (bundle exec rails server)
    ? URL of tested API endpoint http://127.0.0.1:8080
    ? Programming language of hooks python
    ? Do you want to use Apiary test inspector? No
    ? Dredd is best served with Continuous Integration.
    Create CircleCI config for Dredd? No
    Configuration saved to dredd.yml
    Run test now, with:
    $ dredd

    View full-size slide

  162. Lesson 2.04: Test with Dredd
    How Dredd works
    In request: x-example or default
    In response: format matching

    View full-size slide

  163. Lesson 2.04: Test with Dredd
    Parameter Example
    pet-id:
    name: pet-id
    in: path
    description: Pet identifier
    type: number
    required: true
    x-example: 42

    View full-size slide

  164. Lesson 2.04: Test with Dredd
    Exercise Instructions
    Update all the GET actions so that they can be
    tested using Dredd.
    Initialize dredd and run dredd --method GET
    command in order to verify that tests are passing.
    (Use ids from data you initialized in the application
    in previous lesson)

    View full-size slide

  165. Solution 2.04
    Notes
    4 tests passed and 6 skipped.

    View full-size slide

  166. Lesson 2.05: New Features
    Goals
    Development cycle for new feature

    View full-size slide

  167. Lesson 2.05: New Features
    Flow
    Update the spec
    Run tests -> Fail
    Update the code
    Run tests -> Success

    View full-size slide

  168. New Feature Demo

    View full-size slide

  169. Lesson 2.05: New Features
    Exercise Instructions
    Add a new feature to the application to support
    reviews. Besides a unique id the review object
    should reference the talk_id it refers to and
    details .

    View full-size slide

  170. Solution 2.05
    Notes
    Connecting it all together

    View full-size slide

  171. Lesson 2.06: Documentation
    Goals
    Generating automatic documentation for clients

    View full-size slide

  172. Lesson 2.06: Documentation
    Tooling
    Connexion: HTML, Console
    swagger-ui
    Many others

    View full-size slide

  173. Connexion Docs
    Demo

    View full-size slide

  174. Lesson 2.06: Documentation
    Exercise Instructions
    Register a new speaker and submit a talk using the
    connexion UI.
    Use the UI to also update and delete the talk and
    the speaker.

    View full-size slide

  175. Solution 2.06
    Notes
    Easy to distribute documentation

    View full-size slide

  176. Part 2 Recap
    2.01: Code Generation
    2.02: Run the API
    2.03: Mock Server
    2.04: Test with Dredd
    2.05: New Features
    2.06: Documentation

    View full-size slide

  177. More Resources
    BetterAPIs.com

    View full-size slide

  178. Ian
    [email protected]
    @izcoder
    Thank You!
    Questions?
    Dave
    [email protected]
    @tylerdave

    View full-size slide