How to Write Open API 3.x Specifications

How to Write Open API 3.x Specifications


API First

When implementing capabilities, the design of the services must start with the externally visible service contract specification (the API). An API is a contract that all parties need to follow exactly. Changing such a contract is always difficult. This makes the design stage of an API extremely important.

OpenAPI 3

OpenAPI Latest Specs

The industry standard for REST API definition is the OpenAPI Specification (OAS). OpenAPI Specification (renamed from the Swagger Specification to OpenAPI Specification in 2015) is an API specification format for REST APIs.

An OpenAPI specs allows you to describe your API, including:

  • Available endpoints i.e., (/track) and operations on each endpoint (GET /users, POST /users)
  • Operation parameters Input and output for each operation
  • Authentication methods
  • Corporate information, license, terms of use and other information.

API specifications can be written in YAML or JSON. Writing specifications in YAML is highly recommended because it is more human-readable format.

Best Practices

Tools

Swagger editor and hub are built and contributed by Smartbear.

Swagger Editor

https://editor.swagger.io

Swagger is a node application which can be installed on a desktop and?the online editor?works just as fine ;

Swagger Hub

https://app.swaggerhub.com

Swagger hub gives more control over API specifications and allows developers to develop API specifications collaboratively. (Signup is required).

Swagger Codegen

The Swagger Codegen is an open-source code-generator to build server stubs and client SDKs directly from a Swagger-defined RESTful API. The source code for the Swagger Codegen can be found on GitHub.

GitHub:?https://github.com/swagger-api/swagger-codegen

Various parts of a well-defined API Specification

API General Information

openapi: 3.0.0info:
# You application title. Required.
  title: Ping App

# API version. You can use semantic versioning like 1.0.0,
# or an arbitrary string like 0.99-beta. Required.
  version: 1.0.0

# API description. Arbitrary text in CommonMark or HTML.
  description: This is a Ping API description

# Link to the page that describes the terms of service.
# Must be in the URL format.
  termsOfService: <https://example.com/terms/>

# Contact information: name, email, URL.
  contact:
    name: API Support
    email: [email protected]
    url: <https://example.com/support>

# Name of the license and a URL to the license description.
  license:
    name: Apache 2.0
    url: <https://www.apache.org/licenses/LICENSE-2.0.html>

# Link to the external documentation (if any).
# Code or documentation generation tools can use description as the text of the link.
  externalDocs:
    description: Find out more
    url:<https://example.com>
        

Auth

Describing Bearer Authentication

Bearer authentication means “give access to the bearer of this token.” The bearer token is a cryptic string, usually generated by the server in response to a login request. The client must send this token in the Authorization header when making requests to protected resources:

Authorization: Bearer <token>
        

JWT Tokens

JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret or a public/private key pair using RSA or ECDSA.

1. Define Security Scheme for JWT tokens

securitySchemes:
      bearerAuth:
        type: http
        scheme: bearer
        bearerFormat: JWT
        

Since bearer tokens are usually generated by the server, bearerFormat is used mainly for documentation purposes, as a hint to the clients. In the example above, it is “JWT”, meaning JSON Web Token.

2. Apply security scheme

Following applies the security globally to all operations

security:
  - bearerAuth: []
        

The square brackets [] in bearerAuth: [] contain a list of security scopes required for API calls. The list is empty because scopes are only used with OAuth 2 and OpenID Connect. In the example above, Bearer authentication is applied globally to the whole API.


Components

Components serve as a container for various reusable definitions:

  • schemas (data models),
  • parameters,
  • responses,
  • examples, and others.

The definitions in components have no direct effect on the API unless you explicitly reference them from somewhere outside the components.

Here is the list of what you can put into your OpenAPI 3 components object, and reference throughout your API definitions:

schemas — An object to hold reusable data schema used across your definitions.

responses — An object to hold reusable responses, status codes, and their references.

parameters — An object to hold reusable parameters you are using throughout your API requests.

examples — An object to hold reusable the examples of requests and responses used in your design.

requestBodies — An object to hold reusable the bodies that will be sent with your API request.

headers — An object to hold reusable headers that define the HTTP structure of your requests.

securitySchemes — An object to hold reusable security definitions that protect your API resources.

links — An object to hold reusable links that get applied to API requests, moving it towards hypermedia.

callbacks — An object to hold reusable callbacks that can be applied.

All subsections are optional.

The component names are used to reference the components via $ref from other parts of the API specification:

For example:?components: schemas: Item: type: object ... Customer: type: object

Item can be referenced as:

$ref: '#/components/schemas/Item'
        

Parameter type

OpenAPI 3 distinguishes between the following parameter types based on the parameter location. The location is determined by the parameter’s in key, for example, in: query or in: path.

  1. path parameters, such as?/users/{id}
  2. query parameters, such as?/users?role=admin
  3. header parameters, such as X-MyHeader:?Value
  4. cookie parameters, which are passed in the Cookie header, such as?Cookie: debug=0; csrftoken=BUSe35dohU3O1MZvDCU

Reference:?https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject

Paths

API paths and operations are defined in the global paths section of the API specification.

paths:
  /ping:
    ...
  /track:
    ...
        

Deprecated operations

You can mark specific paths as deprecated to indicate that they should be transitioned out of usage:

/item/findByTags:
  get:
    **deprecated**: true
        

HTTP methods

For each path, you define operations (HTTP methods) that can be used to access that path.

OpenAPI 3 supports:

  • get
  • post
  • put
  • patch
  • delete
  • head
  • options
  • and trace.

get

paths:
paths:
  /login:
    get:
      security:
        - bearerAuth: []
        

Parameters

You can use curly braces {} to mark parts of an URL as path parameters:

/item/{ids…}
        

Query String in Paths

Query string parameters must not be included in paths. They should be defined as query parameters instead.

Incorrect:

paths:
  /item?type={type}:
        

Correct:

paths:
  /item:
    get:
      parameters:
        - in: query
          name: type
          schema:
            type: string
            enum: [type1, type2, type3]
          required: true
        

post

To illustrate form data, consider an HTML POST form:

<form action="<https://example.com/survey>" method="post">
  <input type="text"   name="name" />
  <input type="number" name="fav_number" />
  <input type="submit"/>
</form>
        

This form POSTs data to the form’s endpoint:

POST /survey HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
name=Amy+Smith&fav_number=42
        

In OpenAPI 3, form data is modelled using a type: object schema where the object properties represent the form fields:

paths:
  /survey:
    post:
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                name:# <!--- form field name
                  type: string
                fav_number:# <!--- form field name
                  type: integer
              required:
                - name
                - email
        

put

PUT method intends to replace an existing resource.

For example:

paths:
  /avatar:
    put:
      summary: Upload an avatar
      requestBody:
        content:
          image/*:    # Can be image/png, image/svg, image/gif, etc.
            schema:
              type: string
              format: binary
        

delete

Delete removes a resource. For example:

delete:
      description: deletes a single item based on the ID supplied
      operationId: deleteItem
      parameters:
        - name: id
          in: path
          description: ID of item to delete
          required: true
          type: integer
          format: int64
      responses:
        "204":
          description: item deleted
        

Request Body

OpenAPI 3 uses the requestBody keyword to distinguish the payload from parameters (such as query string). The requestBody is more flexible in that it lets you consume different media types, such as JSON, XML, form data, plain text, and others, and use different schemas for different media types. requestBody consists of the content object, an optional Markdown-formatted description, and an optional required flag (false by default). content lists the media types consumed by the operation (such as application/json) and specifies the schema for each media type.

paths:
  /items:
    post:
      summary: Add a new item
      requestBody:
        description: Optional description in *Markdown*
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Item'
          application/xml:
            schema:
              $ref: '#/components/schemas/Item'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ItemForm'
          text/plain:
            schema:
              type: string
      responses:
        '201':
          description: Created
        

Request bodies are optional by default. To mark the body as required, use required: true.

Response Body

Each operation within API specifications must have at least one response defined, usually a successful response. A response is defined by its HTTP status code and the data returned in the response body and/or headers.

Media Types

An API can respond with various media types. JSON is the most common format for data exchange, but not the only one possible. To specify the response media types, use the content keyword at the operation level.

paths:
  /items:
    get:
      summary: Get all items
      responses:
        '200':
          description: A list of items
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayOfItems'
            application/xml:
              schema:
                $ref: '#/components/schemas/ArrayOfItems'
            text/plain:
              schema:
                type: string
  # This operation returns image
  /logo:
    get:
      summary: Get the logo image
      responses:
        '200':
          description: Logo image in PNG format
          content:
            image/png:
              schema:
                type: string
                format: binary
        

HTTP Response Codes

Under responses, each response definition starts with a status code, such as 200 or 404. An operation typically returns one successful status code and one or more error statuses. To define a range of response codes, you may use the following range definitions: 1XX, 2XX, 3XX, 4XX, and 5XX.

responses:
        '200':
          description: OK
        '400':
          description: Bad request. Item ID must be an integer and larger than 0.
        '401':
          description: Authorization information is missing or invalid.
        '404':
          description: A user with the specified ID was not found.
        '5XX':
          description: Unexpected error.
        

Errors

Following definition returns 401 error if user isn’t authorized:

paths:
  /ping:
    get:
      ...
      responses:
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        ...
    post:
      ...
      responses:
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        ...
components:
  responses:
    UnauthorizedError:
      description: Access token is missing or invalid
        

Example OpenAPI 3.0 Specifications

openapi: 3.0.0
# Created by Mazhar Choudhryinfo:
  version: "1.0.0"
  title: Ping API with Auth
  description: >-
    API to Ping
  termsOfService: <https://example.com/terms-of-use>
  contact:
    name: Mazhar Choudhry
    url: <https://mazrnow.com>
  license:
    name: Objex License
    url: <https://license.example.com>
servers:
# Added by API Auto Mocking Plugin
  - description: SwaggerHub API Auto Mocking
    url: <https://virtserver.swaggerhub.com/mazrc/Track/1.0.0>
  - description: dev server
    url: dev.example.com/v1
  - description: prod server
    url: prod.example.com/v1

paths:
  /login:
    get:
      summary: Return JWT token
      description: >-
        This is an example opeartion to show how security is applied to the
        call.
      responses:
        '200':
          description: OK
  /ping:
    get:
      summary: Server heartbeat operation
      description: >-
        This operation shows how to override the global security defined above,
        as we want to open it up for all users.
      security: []
      responses:
        '200':
          description: OK
components:
  schemas: {}

# Security Scheme
  securitySchemes:
      bearerAuth:
        type: http
        scheme: bearer
        bearerFormat: JWT# we can use this to pass in customer

# Apply the security globally to all operations
security:
  - bearerAuth: []
        

Open API 3.1 Update

Open API 3.1 updated the specifications, major change is a webhooks native support:

Webhooks

Webhooks provide a mechanism where by a server-side application can communicate with a client application when a new event (that the client-side application is subscribed to) has occurred on the server side.

webhooks:
  itemShipped:
    post:
      requestBody:
        description: Information about item shipped
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Item"
      responses:
        "200":
          description: Return a 200 status to indicate that the data was received successfully
        

Other updates

Additions

  • Added the?jsonSchemaDialect?top-level field to allow the definition of a default $schema value for Schema Objects.

Updates

  • Updated some links to more accurate locations.
  • Updates JSON Schema support to the latest?2020-12 draft.
  • Revamped relative reference ($ref) resolution under both URIs and URLs.
  • Reworked file upload description to take into account new JSON Schema capabilities. This contains breaking changes.
  • Both?x-oai-?and?x-oas-?prefixes for Specification Extensions are now reserved to be defined by the OpenAPI Initiative.

References


Author

Mazhar Choudhry is a Cloud Solutions Architect who also architected and developed a Social First Media marketing web application Rabbito Social Hub https://rabbito.io ?Follow the link to benefit from the special promotion.

要查看或添加评论,请登录

Objex的更多文章