OpenAPI Specification 入門

0 件のコメント

今回は「OpenAPI Specification の使い方」についてまとめます。 OpenAPIに触れるとでてくる Swagger についても、位置づけや役割もあわせてまとめています。

概要

REST API を設計する際に使う「API設計書記述の仕様」です。

OpenAPI Specification を使ってAPIを定義すると「利用可能なエンドポイントおよびそのエンドポイントで可能な操作のイン/アウト」を定義できます。

OpenAPIを使った仕様書は JSON か YAML 形式で記述します。

Swaggerとは「OpenAPI Specification を使って設計/開発を行うためのツール群」です。 主要なツールは以下の3ツールです。

Swagger Editor
ブラウザ上で利用可能なOpenAPIに従った記述を行うためのエディタ
Swagger UI
作成したOpenAPI仕様書をもとにAPIドキュメントとして表示させるビューア
Swagger Codegen
作成したOpenAPI仕様書をもとにスタブやクライアントを作成するジェネレータ

上記ツールはいずれもGitHub上で公開されており、DockerHubにもイメージが公開されています。 中身や使い方が確認したければ GitHub を確認し、とりあえず利用したければ DockerHub のイメージを利用するのがよさそうです。

データ型

基本的にはJSONスキーマに従ったプリミティブ型が利用可能です。 OpenAPIでは一般的な「型」に加えて「フォーマット」が指定できます。 「フォーマット」を使うとより柔軟な型定義ができます。

type format 説明
integer int32 符号付き32ビット整数。
integer int64 符号付き64ビット整数。 いわゆる long 型。 APIのレスポンスではうまく処理できないケースがあるので文字列にすることも考える。
number float 浮動小数。
number double 倍精度浮動小数。
string ― 文字列。
string byte Base64エンコードされた文字列。
string binary バイナリ文字列。
boolean ― 真偽。
string date RFC3339のfull-date形式文字列(=W3C-DTFのComplete Date)。
YYYY-MM-DD(例: 1997-07-16)。
string date-time RFC3339のdate-time形式文字列(=W3C-DTFのComplete date plus hours, minutes and seconds)。
YYYY-MM-DDThh:mm:ssTZD(例: 1997-07-16T19:20:30+01:00)。
string email メールアドレス。
string password パスワード。
string uuid UUID。

基本構造

OpenAPI Specification の基本構造は以下のようになっています。

openapi: "3.0.0"

info:
  ...

servers:
  ...

tags:
  ...

paths:
  ...

components:
  ...

フィールド 型 説明
openapi string 必須
OpenAPIのどのバージョンを利用して記述しているかを定義する。 バージョンはセマンティックバージョニングで定義されており、記述もセマンティックバージョニングに従って記述する。
info object 必須
APIのメタデータを定義する。
servers [object] APIを提供するサーバーを配列で記述する。
tags [object] APIを整理するために利用するタグを定義する。
paths object 必須
APIとして利用可能なパスおよび操作を定義する。
components object いろいろなオブジェクトをコンポーネントとして再利用可能な形で定義する。

スキーマ詳細

info には、API自体のメタデータを定義します。

info:
  title: "Sample API"
  description: "Sample API provides sample function."
  version: "1.0.0"
フィールド 型 説明
title string 必須
APIのタイトルを定義する。
description string APIに関する説明を定義する。マークダウンを使ってリッチテキスト表示もできる。
versioin string 必須
記述しているAPI設計書(openapi.yaml自身)のバージョン。

APIを提供しているサーバーを定義します。 開発環境であれば localhost 、他にもステージングやプロダクションなどを定義します。

servers:
- url: "http://localhost:3000"
  description: "Local machine"
- url: "http://api.sample.com"
  description: "Production Server"
フィールド 型 説明
url string 必須
APIを提供しているサーバーアドレスを記載する。
description string 提供サーバーに関する補足情報を記載する。

APIを整理するために使用するタグを配列で定義します。 ここで定義されたタグは定義された順に表示されます。 APIで利用するタグすべてを定義する必要はありませんが、自動作成されるタグはここで定義されたタグの後ろに追加されます。 タグなしのAPIは default という名前のタグが割り当てられます。

tags:
- name: "shops"
  description: "Shop operations."

フィールド 型 説明
name string 必須
タグ名を定義する。
description string タグに関する説明を記載する。 マークダウンを利用したリッチテキスト表記も可能。

APIとして利用可能なパスおよび操作の実態を定義します。

paths:
  "/shops/{shopId}/reviews":
    post:
      summary: "Create new review."
      description: "Add new specified shop's review."
      tags: ["shops"]
      deprecated: false
      parameters:
      - name: "shopId"
        in: "path"
        description: "Specified shop ID"
        required: true
        schema: { type: string }
      requestBody:
        description: "Review contents"
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                score: { type: integer, format: int32 }
                comment: { type: string }
      responses:
        201:
          description: "Success response"
      security:
      - sample_oauth2_auth: ["create_review"]

少し量が多いので以下のように分割して見ていきます。

  • パス、メソッド、操作
  • リクエストパラメータ
  • リクエストボディー
  • レスポンス
  • セキュリティ

パス、メソッド、操作

paths:
  "/shops/{shopId}/reviews":
    post:
      summary: "Get specified shop's reviews."
      description: "Get specified shop's reviews."
      tags: ["shops"]
      deprecated: false
      parameters:
        ...
      requestBody:
        ...
      responses:
        ...
      security:
        ...
フィールド 型 説明
{path} object エンドポイントになる相対パスを定義する。 パスは必ず "/"(スラッシュ) から始まるよう記述する。 パスパラメータを指定したい場合、 "{}"(波括弧) で表現する。
{path}.{method} object パスに対する操作を定義する。 定義できる操作は以下の通りで、 connect 以外が利用可能です。
  • get
  • put
  • post
  • delete
  • options
  • head
  • patch
  • trace
{path}.{method}.summary string 操作に関する簡単な説明を記載します。
{path}.{method}.description string 操作に関する詳細説明を記載します。 マークダウンを利用してリッチテキスト表記もできる。 APIの処理詳細を記載します。マークダウン形式で記載ができます。
{path}.{method}.tags [string] タグを配列で言指定する。 タグをつけることでAPIをグルーピングすることができます。
{path}.{method}.deprecated boolean 廃止になった操作かどうかを定義します。 デフォルト false 。
{path}.{method}.parameters object リクエストパラメータ情報を定義します。
{path}.{method}.requestBody object リクエストボディー情報を定義します。
{path}.{method}.responses object レスポンス情報を定義します。
{path}.{method}.security object セキュリティに関する定義をします。

リクエストパラメータ

paths:
  "/shops/{shopId}/reviews":
    get:
      ...

      parameters:
      - name: "shopId"
        in: "path"
        description: "Specified shop ID"
        required: true
        schema: { type: "string", format: "uuid" }
      - name: "order"
        in: "query"
        description: "Response sort order"
        required: true
        schema:
          type: string
          enum: ["asc", "desc"]

      responses:
        ...
      security:
        ...
フィールド 型 説明
name string 必須
パラメータ名を指定します。 in: path の場合、パス中のパラメータ名と一致させる必要があります。
in string 必須
パラーメータの場所を指定します。 指定できる値は以下の通りです。
  • path
  • query
  • header
  • cookie
description string パラメータに関する説明を記載します。 マークダウンも利用可能です。
required boolean in: path の場合は 必須
パラメータの必須/非必須を定義します。 デフォルトは false。
schema object パラメータの型定義をします。 JSONスキーマを元にした記述をします。

リクエストボディー

paths:
  "/shops/{shopId}/reviews":
    post:
      ...

      parameters:
        ...

      requestBody:
        description: "Review contents"
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                score: { type: integer }
                comment: { type: string }

      responses:
        ...
      security:
        ...
フィールド 型 説明
description string リクエストボディーに関する説明を記載します。
required boolean リクエストボディーが必須かどうかを指定します。デフォルトは false 。
content object 必須
リクエストボディーの内容を定義します。 値に設定できるのは Media-Type を値。
content.{media} object メディアタイプをキーにレスポンスボディーを定義します。
content.{media}.schema object リクエストボディーの定義をします。 JSONスキーマを元にした記述をします。

レスポンス

paths:
  "/shops/{shopId}/reviews":
    get:
      ...
      parameters:
        ...

      responses:
        200:
          description: "Success response."
          headers:
            X-RateLimit-Remaining:
              description: "Number of remaining requests in the currenct period."
              schema: { type: integer }
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    score: { type: integer }
                    comment: { type: string }

      security:
        ...
フィールド 型 説明
{status} object {status}に定義したいステータスコードを指定します。 ステータスコードをキーとしてレスオンスの内容を定義します。
{status}.description string 該当ステータスコードのレスポンス概要を記載します。
{status}.headers object レスポンスに含まれるヘッダーを定義します。
{status}.headers.{header} object {header}に定義したいヘッダー名を指定します。 ヘッダー名をキーとしてヘッダー情報の内容を定義します。
{status}.headers.{header}.description object レスポンスヘッダーの概要説明を記載します。
{status}.headers.{header}.schema object レスポンスヘッダーのスキーマを定義します。
{status}.content object レスポンスの中身を定義します。
{status}.content.{media} object レスポンスのメディアタイプをキーに内容を定義します。
{status}.content.{media}.schema object レスポンスのスキーマを定義します。

セキュリティ

paths:
  "/shops/{shopId}/reviews":
    post:
      ...
      parameters:
        ...
      requestBody:
        ...
      responses:
        ...

      security:
      - sample_oauth2_auth: ["create_review"]

フィールド 型 説明
{name} [string] {name} には /components/securitySchemes に定義したセキュリティ名を指定します。 指定する配列には必要とするスコープ名を定義します。 apiKey や http で特にスコープが必要ない場合、空配列にします。

components

OpenAPI中で再利用可能なコンポーネントを定義します。 定義できるものとしては以下のようなものがあります。

今回はこのうちよく利用しそうな「schemas」と「securitySchemes」を取り上げます。

components:
  schemas:
    ...

  responses:
    ...

  parameters:
    ...

  examples:
    ...

  requestBodies:
    ...

  headers:
    ...

  securitySchemes:
    ...

componentsを利用するときは $ref を使って以下のように参照させます。

paths:
  "/shops/{shopId}/reviews":
    post:
      ...
      requestBody:
        ...
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Review"
  • プリミティブ

    components:
      schemas:
        ShopId:
          type: string
          format: uuid
          example: "SAMPLE-SHOP-ID-XXXXXX"
    
  • 列挙

    components:
      schemas:
        SortOrder:
          type: string
          enum: [asc, desc]
    
  • オブジェクト

    components:
      schemas:
        Review:
          type: object
          example: { score: 4, comment: "Sample review comment." }
          properties:
            score:
              type: integer
              format: int32
            comment:
              type: string
    
  • 配列

    components:
      schemas:
        ReviewList:
          type: array
          items:
            $ref: "#/components/schemas/Review"
    
フィールド 型 説明
{name} object スキーマとして定義する任意の名前を指定します。
{name}.type string 型を定義します。
{name}.description string スキーマに関する説明を記述します。
{name}.format string プリミティブ型の場合、追加のフォーマット指定があれば定義します。
{name}.enum [any] 決められた値から選択される場合、選択可能な値を定義します。
{name}.properties object type: object の場合、オブジェクトの内容を定義します。
{name}.items object type: array の場合、配列の内容を定義します。
{name}.default any デフォルト値を定義します。
{name}.example any サンプルを定義します。

  • JWT

    components:
      securitySchemes:
        sample_jwt_auth:
          type: http
          description: "Sample Service original authorization."
          scheme: bearer
          bearerFormat: JWT
    
  • API Key

    components:
      securitySchemes:
        sample_apikey_auth:
          type: apiKey
          description: "Sample Service API-Key authorization."
          in: header
          name: X-Api-Key
    
  • OAuth2

    components:
      securitySchemes:
        sample_oauth2_auth:
          type: oauth2
          flows:
            authorizationCode:
              authorizationUrl: "https://oauth.sample.com/auth"
              tokenUrl: "https://oauth.sample.com/token"
              scopes:
                "create_review": "Post new review."
    
  • OpenIDConnect

    components:
      securitySchemes:
        sample_oidc_auth:
          type: openIdConnect
          openIdConnectUrl: "https://oidc.sample.com/signin"
    
  • Cookie

    components:
      securitySchemes:
        sample_cookie_auth:
          type: apiKey
          in: cookie
          name: JSESSIONID
    
フィールド 型 説明
type string 必須
以下のいずれかを指定します。
  • apiKey
  • http
  • oauth2
  • openIdConnect
description string セキュリティスキーマの説明を記載します。
name string type: apiKey の場合、必須
ヘッダー、クエリ―、クッキーのキー名を指定します。
in string type: apiKey の場合、必須
APIキーがどこにあるかを以下から指定します。
  • query
  • header
  • cookie
scheme string type: http の場合、必須
IANAのスキーマレジストリに登録されたものを指定します。 以下のような値が指定できます。
  • basic
  • bearer
  • digest
bearerFormat string type: http, scheme: bearer のとき定義できます。
Authorizationヘッダーに入れるフォーマットを指定します。 ほぼ JWT しか入らなさそう。
flows object type: oauth2 の場合、必須
OAuth2 のフローを定義します。
flows.{flow} object {flow} には以下のいずれかを指定します。
  • implicit
  • password
  • clientCredentials
  • authorizationCode
flows.{flow}.authorizationUrl string {flow}: implicit, authorizationCode の場合、必須
認可エンドポイントのURLを定義します。
flows.{flow}.tokenUrl string {flow}: password, clientCredentials, authorizationCode の場合、必須
トークン取得するエンドポイントのURLを定義します。
flows.{flow}.refreshUrl string リフレッシュトークンを取得するエンドポイントのURLを指定します。
flows.{flow}.scopes objecct 必須
利用可能なスコープを定義します。
flows.{flow}.scopes.{scope} string キー({scope})にスコープ名を定義し、バリューに該当スコープの説明を定義します。
openIdConnectUrl string type: openIdConnect の場合、必須
OpenIDConnectディスカバリーのエンドポイントURLを指定します。

今回は「OpenAPI Specification の使い方」についてまとめました。 参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!

参考記事

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!