39
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

株式会社CAMAdvent Calendar 2019

Day 10

OpenAPI 3のドキュメントの一部翻訳

Last updated at Posted at 2019-12-09

はじめに

株式会社CAM のAdvent Calendar 10日目です。
昨日は @ohteru さんの「DIPについて勉強し直してみた」でした。

僕は最近Open APIやSwaggerに触れるようになったのですが、呼び方が違ったり、色々ツールがあったりでさっぱり理解できませんでした。そこで、公式のページをみていたのですが、公式は英語しかないのでちょっと辛いなと思い、自分が勉強した部分のみ翻訳をしてみました。

What is OpenAPI?

OpenAPI Specification(この前までのSwagger Specification)は REST APIの記述フォーマットです。
OpenAPI fileはAPIを以下の要素を含ませて定義できます。

  • 利用可能なエンドポイント(/users)とその操作(GET /users, POST /users)
  • それぞれのオペレーションの入力と出力
  • 認証メソッド
  • ライセンス、利用規約、問い合わせ先などの情報

API SpecificationはYAMLまたはJSONで記述できます。フォーマットは簡単で、機械にも人間にも読みやすいものになっています。
完全なOpenAPI Specificationは Github上で確認できます。

What is Swagger?

SwaggerとはOASに関連して作られ、設計したり、ビルドしたり、仕様書の作成を手助けしてくれるオープンソースツールの集まりのことです。
主なツールは

  • Swagger Editor - OASを書くことができるブラウザベースのエディタです。
  • Swagger UI - OASをインテラクティブなAPI仕様書として表示するツールです。
  • Swagger Codegen - サーバのスタブやOASのクライアントのsdkを生成するツールです。

Why Use OpenAPI?

API構造を書き上げることはOpen APIにおけるはじめの一歩です。一度書けば、OASとSwagger toolsが様々な方法でAPI開発を手助けします。

  • Swagger Codegenを用いてAPIサーバのstubを生成することができます。サーバーのロジックを追加するだけでstubを動かすことができます。
  • Swagger Codegenでクライアントのライブラリを生成することができます。40以上の言語に対応しています。
  • Swagger UIを用いることでドキュメントを生成することができ、ブラウザ上でAPIを試すことができます。
  • specをAPI関連ツールに繋げることができます。例えば、specをSoupUIに取り入れることで、APIの自動テストを行うことができます。
  • ほかのSwaggerと連携するツールもopen-sourcecommercial toolsでチェックしましょう!

Basic Structure

OpenAPIはYAMLとJSON形式で記述できます。こちらではYAMLでの例を示しますが、JSONでも同様に動作します。
OpenAPI 3.0のYAMLでの定義はこのようになります。

.yaml
openapi: 3.0.0
info:
  title: Sample API
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: 0.1.9
servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML.
      responses:
        '200':    # status code
          description: A JSON array of user names
          content:
            application/json:
              schema: 
                type: array
                items: 
                  type: string

すべてのキーワードは case-sensitiveです。

case-sensitiveとは

プログラムの大文字と小文字を区別数プログラムの性能のこと。
簡単に説明すると、RUNとrunを別のものとして識別します。
文字の大文字小文字を区別しないプログラミング言語は case-insensitiveです。

参考文献

Metadata

API定義は必ず OpenAPI Specificationのバージョンを含めなければなりません。

.yaml
openapi: 3.0.0

OpenAPIバージョンは、何をどのようにしようとして書くかといったAPI定義の全体構造を決めます。
OpenAPI 3.0は semantic versioningという三つの数字を用いた表現方法を用います。
利用可能なバージョンは、3.0.0, 3.0.1, 3.0.2です。これらの機能はすべて同じです。

info節には、title, descrirption, versionといったAPIの情報を含みます。

.yaml
info:
  title: Sample API
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: 0.1.9

titleはAPIの名前、descriptionはAPIに関する追加の情報です。これはmultiline CommonMark

Servers

servers節にはAPIサーバとbase URLを詳述します。一つまたは複数を定義できます。
例、本番環境と開発環境(sandbox)

.yaml
servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing

すべてAPIのパスはこのserverのURLに紐付きます。上記の例では、/usersは選択されているサーバによって
http://api.example.com/v1/users または http://staging-api.example.com/users
となります。詳しい情報はこちらです。

Paths

paths節ではAPI、HTTPメソッド(オペレーション)のそれぞれのエンドポイントを定義できます。例として、GET /usersは以下のように表現できます。

.yaml
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML
      responses:
        '200':
          description: A JSON array of user names
          content:
            application/json:
              schema: 
                type: array
                items: 
                  type: string

オペレーションの定義には、パラメータ、リクエストのbody、レスポンスのステータスコード(200 OK, 404 Not Found)などやレスポンスの内容が含まれます。詳しい情報は、Paths and Operationsをご確認ください。

Parameters

オペレーションはURLのpathを通して、あるいはクエリ文字列で、あるいはヘッダーやクッキーでパラメータを持ちます。
パラメータはデータ型、フォーマット、それが必須か任意かなどの詳細情報を定義できます。

.yaml
paths:
  /user/{userId}:
    get:
      summary: Returns a user by ID.
      parameters:
        - name: userId
          in: path
          required: true
          description: Parameter description in CommonMark or HTML.
          schema:
            type : integer
            format: int64
            minimum: 1
      responses: 
        '200':
          description: OK

詳しく知りたい方はDescribe Parametersをご覧ください。

RequestBody

もしリクエストがbodyを送信する場合、requestBodyキーワードでbodyの内容とmediaタイプを設定してください。

.yaml
paths:
  /users:
    post:
      summary: Creates a user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
      responses: 
        '201':
          description: Created

追加情報は、Describing Request Bosyをご確認ください。

Responses

それぞれのHTTPメソッドにおいて、200 OKや404 Not Foundのステータスコードとレスポンスのbodyを定義できます。
schemaはそのまま中に書くか$refで参照するかで定義できます。それぞれの異なるcontentsのタイプに対して例を追加することができます。

.yaml
paths:
  /user/{userId}:
    get:
      summary: Returns a user by ID.
      parameters:
        - name: userId
          in: path
          required: true
          description: The ID of the user to return.
          schema:
            type: integer
            format: int64
            minimum: 1
      responses:
        '200':
          description: A user object.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    format: int64
                    example: 4
                  name:
                    type: string
                    example: Jessica Smith
        '400':
          description: The specified user ID is invalid (not a number).
        '404':
          description: A user with the specified ID was not found.
        default:
          description: Unexpected error

レスポンスのHTTPステータスコードは"で"200"のように囲む必要があります(OpenAPI 2.0では囲む必要はありません)。
もっと知りたい方はこちらをご覧ください。

Input and Output Models

components/schemas節にはAPI全体でつかわれるデータ構造を定義できます。これらは、パラメータやリクエストのbody、レスポンスのbodyにschemaが必要な時に$refによって追加する。
例えば、このJSONオブジェクトは

.json
{
  "id": 4,
  "name": "Arthur Dent"
}

はこのように置き換えられます。

.yaml
components:
  schemas:
    User:
      properties:
        id:
          type: integer
        name:
          type: string
      # Both properties are required
      required:  
        - id
        - name

そして、リクエストのbodyとレスポンスのbodyのschemaはこのように参照されます。

.yaml
paths:
  /users/{userId}:
    get:
      summary: Returns a user by ID.
      parameters:
        - in: path
          name: userId
          required: true
          type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
  /users:
    post:
      summary: Creates a new user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '201':
          description: Created

Authentication

securitySchemassecurityキーワードは、APIで使われている認証メソッドを表現します。

.yaml
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
security:
  - BasicAuth: []

サポートされている認証方法は以下の通りです。

  • HTTP認証 Basic, Bearer, etc..
  • クッキーやクエリ、ヘッダーへのAPIキー
  • OAuth2
  • OpenID Connect Discovery

そのほかの情報はこちらを確認ください。

Full Specification

すべてのOpenAPI 3.0 SpecificationはGithub上で確認できます。
https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md

Data Models(Schemas)

DataTypes

スキーマのデータ型は typeキーワードによって定義されます。例) type: string
OpenAPIは以下の型を定義します。

  • string
  • number
  • integer
  • boolean
  • array
  • object

これらの型は、呼び方は違うかもしれませんが、ほどんどのプログラミング言語に備えてあります。

Mixed Types, Numbers, Minimum and Maximumは省略します。

Strings

テキストの文字列はこのように定義されます。

.yaml
type: string

文字列の長さは minLengthmaxLengthを用いて制限できます。

.yaml
type: string
minLength: 3
maxLength: 10

空の文字列はminLengthpatternを設定しない限り有効です。

String Formats

任意のformat修飾子は文字列のフォーマットや中身についてのヒントを提供します。

  • date - 日付表示 RFC 3339, section 5.6 例) 2017-07-01
  • date-time - 時間表示 RFC 3339, section 5.6 例) 2017-07-21T17:32:28Z
  • password -
  • byte - base64-encoded 文字列 例) U3dhZ2dlciByb2Nrcw==
  • binary -

しかし、formatはオープンな値なのでOASに定義されていない値であっても使用することができます。以下が例です。

  • email
  • uuid
  • uri
  • hostname
  • ipv4
  • ipv6
  • and others..
     
    ツールはフォーマットを入力のバリデーションや、プログラミング言語の特定のタイプに値にするなどに使えます。特定のフォーマットをサポートしていないツールはformatが設定されていない時と同じようにtypeのみを返します。

pattern

patternキーワードは文字列の正規表現テンプレートを定義できます。
このテンプレートに一致する値のみが受け付けられます。正規表現シンタックスはJavaScriptで使われているものです。正規表現はcase-sensitive、つまり大文字と小文字に区別があります。例えば、以下のパターンはSSN(123-45-6789)のフォーマットと一致します。

.yaml
ssn:
  type: string
  pattern: '^\d{3}-\d{2}\d{4}$'

正規表現は^...$によって囲まれること、そして^は文字列の始め、$は文字列の終わりを示します。もし ^..$がない場合、部分一致として動作するので、正規表現として書かれている文字列を含むものが一致します。例えば、pattern:petはpet, petstoreやcarpetを一致とみなします。

Boolean, Null, Arrays, Objects, Files, Any Type, Authentucationは省略します。

Authentication and Authorization

Describing Security

セキュリティは securitySchemessecurityキーワードを使って表現します。securitySchemesはAPIが提供するすべてのセキュリティスキーマを定義し、 securityで全てのAPIまたは一部のオペレーションに適用します。

Step 1. Defining securitySchemes

セキュリティスキーマはすべて components/securitySchemes節で定義される必要があります。ここではセキュリティスキーマのtypeについて説明します。

  • http - Basic、BearerとHTTP認証スキーマ
  • apiKey - APIキーとクッキー認証
  • uauth2 - OAuth2
  • openIdConnect - OpenID Connect Discovery

これに付随するプロパティはそれぞれのtypeに依存します。以下に示すのはそれぞれのセキュリティスキーマがどのように定義されるかを示します。 ここで、BasicAuth, BearerAuthなどの名前はAPIの機能として追加するときに参照される任意の名前です。

.yaml
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
    BearerAuth:
      type: http
      scheme: bearer
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    OpenID:
      type: openIdConnect
      openIdConnectUrl: https://example.com/.well-known/openid-configuration
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://example.com/oauth/authorize
          tokenUrl: https://example.com/oauth/token
          scopes:
            read: Grants read access
            write: Grants write access
            admin: Grants access to admin operations

Step 2. Applying security

securitySchemes節でセキュリティスキーマについて定義した後は、それをAPIやその個々の操作にsecurity節で追加することで適用することができます。rootレベルで適用する場合、security節は設定された認証方法を、オペレーションレベルで上書きされない限りはすべてのAPIとそのオペレーションに適用されます。以下の例は、APIはAPIKeyまたはOauth2を用いて認証されます。 ApiKeyAuthOAuth2という名前は上のsecuritySchemes節で定義されたスキーマを参照します。

.yaml
security:
  - ApiKeyAuth: []
  - OAuth2:
      - read
      - write
# The syntax is:
# - scheme name:
#     - scope 1
#     - scope 2

それぞれのスキーマに対して、APIを呼ぶのに必要な認証方法を指定できます。スコープはOAuth2とOpenID Connect Discoveryのために使われます。他のセキュリティスキーマを利用する場合、代わりに空の配列を使います。全体でのsecurity節はそれぞれのオペレーションに対して違った認証を設定できます(違ったOAuth/OpenIDや、認証を外すことも可能です)。

.yaml
paths:
  /billing_info:
    get:
      summary: Gets the account billing info
      security:
        - OAuth2: [admin]   # Use OAuth with a different scope
      responses:
        '200':
          description: OK
        '401':
          description: Not authenticated
        '403':
          description: Access token does not have the required scope
  /ping:
    get:
      summary: Checks if the server is running
      security: []   # No security
      responses:
        '200':
          description: Server is up and running
        default:
          description: Something is wrong

Scopes

OAuth 2とOpenID Connectはユーザリソースに対する許可を操作するためにスコープを利用します。 例えば、

Basic Authorization

API Keys

APIには認証にAPIキーを用いるものがあります。APIキーとは、クライアントがAPIを呼ぶときに作成したトークンです。キーは以下のようにクエリとして送信できたり、

.yaml
GET /something?api_key=asbnaoirn024

また、ヘッダーとして

.yaml
GET /something HTTP/1.1
X-API-Key: abcdef12345

あるいはクッキーとして送信できます。

.yaml
GET /something HTTP/1.1
Cookie: X-API-KEY=abcdef12345

APIキーは、クライアントとserverしか知らない秘密情報とされています。Basic認証のように、APIキーによる認証はhttps/SSLのようなセキュリティのメカニズムと同じように安全な設計がされています。

Describing API Keys

OpenAPI 3.0では、以下のように定義されます。

.yaml
openapi: 3.0.0
...
# 1) Define the key name and location
components:
  securitySchemes:
    ApiKeyAuth:        # arbitrary name for the security scheme
      type: apiKey
      in: header       # can be "header", "query" or "cookie"
      name: X-API-KEY  # name of the header, query parameter or cookie
# 2) Apply the API key globally to all operations
security:
  - ApiKeyAuth: []     # use the same name as under securitySchemes

この例では、 リクエストのヘッダーとして送られるX-API-Keyという名前のAPIキーを定義します。キー名のApiKeyAuthはセキュリティスキーマ用の名前です。ApiKeyAuthという名前はAPIにセキュリティスキーマを設定するために、security節で再度使われています。注意:securitySchemes節だけに名前を設定するだけでは動作しません。APIキーとしての動作をさせるために、securityでも設定する必要があります。security節は全体ではなく、操作(HTTPMethod)ごとに設定することができます。これは特定の操作のみAPIキーが必要な場合に便利です。

.yaml
paths:
  /something:
    get:
      # Operation-specific security:
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: OK (successfully authenticated)

一つのAPIで複数の認証をサポートすることもできます。 詳しくはこちらを確認ください。

Multiple API Keys

いくつかのAPIでは、API KeyとAppIDのように複数のセキュリティキーを組み合わせて使います。 組み合わせて使われることを明示するには、それらを同じ配列に並べてください。以下が例です。

.yaml
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-KEY
    appId:
      type: apiKey
      in: header
      name: X-APP-ID
security:
  - apiKey: []
    appId:  []   # <-- no leading dash (-)

次のものとは別ものとして認識されます。

.yaml
security:
  - apiKey: []
  - appId:  []

これはどちらでのキーの認証も可能であることを示しています。詳しくは[こちら](https://swagger.io/docs/specification/authentication/#multiple)をご確認ください。

401 Response

401 "Unauthorized" レスポンスをAPIキーが違う、または見つからない場合に返すことができます。このレスポンスはWWW-Authenticateヘッダーを含みます。 他の共通レスポンスと同じように、401レスポンスは全体で利用可能なcomponents/responses節で定義可能で、$refを用いて参照できます。

.yaml
paths:
  /something:
    get:
      ...
      responses:
        ...
        '401':
           $ref: "#/components/responses/UnauthorizedError"
    post:
      ...
      responses:
        ...
        '401':
          $ref: "#/components/responses/UnauthorizedError"
components:
  responses:
    UnauthorizedError:
      description: API key is missing or invalid
      headers:
        WWW_Authenticate:
          schema:
            type: string

詳しく知りたい方は、こちらをご確認ください。

Bearer Authentication

Describing Bearer Authentication

401 Response

適切なBearerトークンを含んでいないリクエストに対し、レスポンスとして返すべき401 Unauthorizedを定義できます。これは複数の操作から呼ばれるであろうことから、components/responses節に書き、

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

余談

YAMLファイルの拡張子について

こちらの記事より抜粋させていただきますと、

3文字拡張子と4文字拡張子

元々は 4文字の拡張子だったものが、Windows 95 の前身である MS-DOS や Windows 3.1 で拡張子を 3文字までしか扱えなかったことから、.html を .htm にしたり、.jpeg を .jpg にしたりなど、拡張子を無理矢理3文字に縮めたものが結構あります。その名残で、現在でも拡張子は 3文字以内にする例が多いようです。

公式?のYAMLに拡張子について質問がされており、理由など詳しい説明はありませんが、.yamlの方でできれば用いてくれとの見解がありました。
https://yaml.org/faq.html

参考文献

https://swagger.io/docs/specification/about/
https://swagger.io/docs/specification/basic-structure/
https://yaml.org

いかがだったでしょうか?

学び始めは正直何を勉強すればいいのか分かりませんでしたが、自分が設定するべき項目をしっかりと調べて一つ一つ構築していくことで理解できるようになると思います。まだまだ学ぶべき機能がたくさんあるので、新しい機能を勉強するたびにこちらの記事に追記していこうと思います。
明日は @maruken24 さんの記事です、お楽しみに。

39
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?