OpenAPIのチュートリアルを自分用にわかりやすくカスタマイズした
業務で使っているけれど、ちゃんと理解してなかったので
一旦Tutorialをやってみました。
概要掴むのに、とても良かったので、意訳しつつ理解したことをまとめました。
詳細はドキュメントを読みにいくのが良いと思います。
OpenAPIとは?
OpenAPI 3.0 is an open-source format for describing and documenting APIs.
OpenAPIとは、API仕様の記述フォーマットです。
2010年にReverb Technologies社によって、
API設計とドキュメントをちゃんとリンクさせるために作られました。
そこから、RESTful APIを定義するときのデファクトスタンダードになっていったらしいです。
ちなみに、Open APIってこんな感じ。
※ JSONかYAMLで書けるけど、YAMLのがシンプルで見やすくておすすめとのこと。
openapi: 3.0.0 info: version: 1.0.0 title: Sample API description: A sample API to illustrate OpenAPI concepts paths: /list: get: description: Returns a list of stuff responses: '200': description: Successful response
チュートリアルをやると、
上記に書かれている内容が理解できるようになります!
OpenAPIを使って仕様書つくると何が嬉しいのか?
そもそも、なんでOpenAPI使うといいね!ってなっているんでしょうか。
OpenAPIを使うと、統一されたフォーマットでAPIドキュメントを作成できたり、
OpenAPIに則ったAPIドキュメントから、APIクライアントの自動生成とかができます。
他にも色々なことができたりするみたいです。
ただ、注意点として、APIの仕様を変更したい場合は、OpenAPIを使った仕様書(ymlファイル)の変更とAPIのロジックの変更の2つが生じます。
間違って、APIのロジックだけ変更とかしてしまうと、仕様書の意味がなくなってしまうので気をつけないといけないです。
これらの点を踏まえて、使う使わないの判断をするのが良いと思います。
チュートリアルについて
チュートリアルでは、Open APIの重要ポイントをさらいながら、
シンプルなAPIを1本作っていきます。
【前提知識】
- RESTful APIに関する基本知識
- YAMLに関する基本知識(推奨)
SwaggerHub’s built-in editor and validatorを使うと、
書いた仕様書がその場で確認できるのでおすすめです!
これからAPIを作るにあたって、例を書いていくので、
それをSwagger Editorを使って、自分でも書いてみましょう。
今回は、1から自分で書いていきたいので、
なるべくシンプルなフォーマットでドキュメントを作ります。
登録後の画面で、左側メニュバーの「Create New」ボタン、
または画面中央に表示されている「CREATE API」ボタンをクリックします。
モーダルが表示されるので、以下のように記載します。
(なるべく自分で1から書いていきたいので、TemplateはNoneにします)
(VisibilityのPrivateは有料プランでないと使えないらしいです...)
(モックAPIサーバーは一旦使いません。)
で、「Create API」ボタンをクリックすると、
以下のドキュメントが生成されました!
このエディタに追記していくことで、ドキュメントを作っていきましょう。
APIを作る
それでは、ユーザー情報を扱うAPIを作成していきます。
各ユーザーは以下のフィールドを持ってるとします。
- ユーザー名
- 氏名
- ユーザーの居住エリア
- ユーザーの年齢
APIは、ユーザー情報の取得と、新しいユーザーの登録ができます。
OpenAPIを使ったAPI定義は、主に3つのセクションに分かれてます。
- Meta information
- Path items (endpoints):
- Parameters
- Request bodies
- Responses
- Reusable components:
- Schemas (data models)
- Parameters
- Responses
- Other components
- メタ情報
- エンドポイント:
- パラメータ一覧
- リクエストボディ一覧
- レスポンス一覧
- 再利用可能なコンポーネント:
- スキーマ(データモデル)
- パラメータ一覧
- レスポンス一覧
- 他のコンポーネント一覧
へー?という感じだと思うので、詳細を見ていきましょう。
Meta information - メタ情報
メタ情報を書いてみましょう。
メタ情報っていうのは、APIのタイトル、バージョン、サーバーURLとか、
その他もろもろの情報のことです。
APIの具体的な中身じゃなくて、APIに関する情報ってことですね。
Swagger Editorには既に記載されているものもありますが、
以下のように追記しましょう。
openapi: 3.0.0
info:
version: 1.0
title: users_api
description: get and post users
// 以下を追記
servers:
- url: https://example.io/v1
// pathはメタ情報ではないので、一旦無視してください
path: {}
openapi
1番最初にどのバージョンのOpenAPIの仕様に則って書いてるかを記述します。
今回はOpenAPI3.0に則って書いてるから、openapi: 3.0.0
(1行目)となります。
info
APIのタイトル(title
)とバージョン(version
)は必須項目なので必ず書いてください。
説明書き(description
)については、任意です。
servers
ここには、サーバーURLを羅列していきます。
※ サーバーURLは1つのときもあると思うけど、
プロダクションとか、サンドボックスとかのサーバーURLを設定することもあるので、
複数設定できるようになってるみたいです。
このサーバーURLの末尾に、後で出てくるAPIのエンドポイントのパスがくっつく形になります。
今回はhttps://example.io/v1
を使います。
※今回は触れないけど、認証まわりも設定できます。
詳しいことについては、以下を読んでみてください。
TODO: ここまで書いた
Path items - エンドポイント一覧
paths配下に操作したいリソースとHTTPメソッドを記述することで、
APIのエンドポイント一覧を定義できます。
ここで定義するエンドポイントの情報とサーバーURL(今回の例だとhttps://example.io/v1
)を合わせて、エンドポイントURLが決まります。
/users
のエンドポイントを作成して、GETメソッドを定義します。
最下部に、以下を追記しましょう。
paths:
/users:
get:
description: ユーザー一覧を取得します
これで、GET https://example.io/v1/users
のエンドポイントを追加できました。
Responses - レスポンス
次はレスポンスの情報を追記します。
レスポンスには、必ずHTTPステータスコードを含みます。
※HTTPステータスコードについては、以下記事が参考になります。
リクエストが成功したらユーザー一覧を返し、
失敗したらエラーメッセージを返す、という定義をしましょう。
以下を追記してください。
paths:
/users:
get:
description: ユーザー一覧を取得します
# ----- ここから下を追加 ----------------------------------------
responses:
'200':
description: ユーザー一覧を返す
content:
application/json:
schema:
type: array
items:
type: object
required:
- username
properties:
username:
type: string
name:
type: string
area:
type: string
age:
type: integer
'400':
description: 不正なリクエスト
content:
application/json:
schema:
type: object
properties:
message:
type: string
# ---- /ここから上を追加 ----------------------------------------
これで、リクエストが成功した場合の200ステータスのレスポンスと
失敗した場合の400ステータスのレスポンスを定義できました。
※レスポンスの記述については、以下の記事で紹介しています。
Parameters - パラメーター
エンドポイントで設定するパラメータについて説明していきます。
※パラメータに関するより詳細な情報は以下記事を参照してください。
Query parameters - クエリパラメーター
クエリパラメータは、よく使われるものの1つですよね。
URL末尾のクエスチョンマーク以降に記述されます。
今回の例では、ユーザー全件を取得してくるのではなく、指定した件数だけ返すようにします。
表示件数(limit)を指定できるようにしましょう。
例:GET https://example.io/v1/artists?limit=20
以下を追記してください。
paths:
/users:
get:
description: ユーザー一覧を取得します
# ----- ここから下を追加 ----------------------------------------
parameters:
- name: limit
in: query
description: 表示件数を制限します
schema:
type: integer
# ---- /ここから上を追加 ----------------------------------------
responses:
'200':
description: ユーザー一覧を返す
content:
...
'400':
description: 不正なリクエスト
content:
...
parameters
配下に、パラメータの情報を記載し、
クエリパラメータを定義できました。
Request body - リクエストボディ
POST, PUT, PATCHメソッドのリクエストは通常リクエストボティを必要とします。
リクエストボディは、requestBody
配下に定義します。
ユーザー情報をPOSTで送信できるようにしましょう。
/users
配下に、POSTメソッドの記述をします。
getと同じ階層に、以下を追記してください。
paths:
/users:
get:
...
# ----- ここから下を追加 ----------------------------------------
post:
description: ユーザーの登録
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- username
properties:
username:
type: string
name:
type: string
area:
type: string
age:
type: integer
responses:
'200':
description: ユーザー登録成功
'400':
description: 不正なリクエスト
content:
application/json:
schema:
type: object
properties:
message:
type: string
# ---- /ここから上を追加 ----------------------------------------
Path parameters - パスパラメーター
パスパラメーターは、特定のデータにアクセスするときなどに使いますよね。
例:https://example.io/v1/users/{username}
パスパラメーターを使う際は、書く順番に気をつけましょう。
書いた順に、パスに反映されます。
(/users/{companyId}/{userId}
だったら、companyId
の方を先に記述する)
それでは、特定のユーザー情報を返すエンドポイントを作成しましょう。
特定のユーザーを取得するにはusername
が必要なので、GETメソッドの配下のparameters
の下に、今回のパスパラメータであるusername
を記述します。
paths:
/users:
get:
description: ユーザー一覧を取得します
...
post:
description: Lets a user post a new artist
...
# ----- ここから下を追加 ----------------------------------------
/users/{username}:
get:
description: ユーザーネームをもとに、ユーザー情報を取得する
parameters:
- name: username
in: path
required: true
schema:
type: string
responses:
'200':
description: ユーザー取得成功
content:
application/json:
schema:
type: object
properties:
username:
type: string
name:
type: string
area:
type: string
age:
type: integer
'400':
description: 不正なリクエスト
content:
application/json:
schema:
type: object
properties:
message:
type: string
# ---- /ここから上を追加 ----------------------------------------
はい!これでパスパラメーターにusername
を指定できました。
必須パラメーターとしているので、呼び出すときは必ず値をセットするようにしてください。
おめでとうございます!
これで、ユーザーを取得してくるAPIの仕様書が作成できました!
Reusable components - 再利用可能なコンポーネント
ここまでで定義したのはたった2つのエンドポイントと3つのアクションだけです。
これは130行の定義になったわけですが、APIの規模が大きくなるにつれてボリュームも増えます。
ここで1つ気づく点としては、ユーザーのスキーマ(ユーザーネーム、氏名、居住エリア、年齢)が繰り返し出てきていることがあります。
なので1度定義したら、それを使いまわせるようにしたい!できます!
それが再利用可能なコンポーネントです。
複数のエンドポイントにまたがって利用できます。
components
配下に定義し、各エンドポイントで呼び出します。
ちなみに色んなもの(例えば以下)を再利用可能なコンポーネントにできます。
- Schemas (data models)
- Parameters
- Request bodies
- Responses
- Response headers
- Examples
- Links
- Callbacks
Schemas - スキーマ
Components
の下のSchemas
配下には、APIで使われるデータモデルを記述できます。
それでは、200ステータスのレスポンスで使うスキーマをコンポーネント化していきます。
以下を追記してください。
paths:
/users:
get:
description: ユーザー一覧を取得します
parameters:
- name: limit
in: query
description: Limits the number of items on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the artists to be displayed
schema:
type: integer
responses:
'200':
description: Successfully returned a list of artists
content:
application/json:
schema:
type: array
items:
# ----- 書き換え ----------------------------------------
$ref: '#/components/schemas/Artist'
# ---- /書き換え ----------------------------------------
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
post:
description: Lets a user post a new artist
requestBody:
required: true
content:
application/json:
schema:
# ----- 書き換え ----------------------------------------
$ref: '#/components/schemas/Artist'
# ---- /書き換え ----------------------------------------
responses:
'200':
description: Successfully created a new artist
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
/users/{username}:
get:
description: Obtain information about an artist from his or her unique username
...
# ----- ここから下を追加 ---------------------------------------- components:
schemas:
User:
type: object
required:
- username
properties:
username:
type: string
name:
type: string
area:
type: string
age:
type: integer
# ---- /ここから上を追加 ----------------------------------------
componentsにスキーマが追加されて、もともとスキーマが書いてあった箇所には、
そのスキーマのリファレンスが記載しました。
定義全体が短くなっただけでなく、
新たにエンドポイントを作るときに再定義する手間がなくなります。
Componentsの詳細については以下の記事を参照してください。
Parameters and Responses - パラメータとレスポンス
componentsセクションには、再利用可能なパラメータやレスポンスも定義することができます。
以下の例では、limit
のクエリパラメータをコンポーネント化し、/users
のエンドポイントで参照するようにしています。
また、400エラーのレスポンスもコンポーネント化し、各エンドポイントから参照できるようにしています。
openapi: 3.0.0
info:
version: 1.0.0
title: Simple API
description: A simple API to illustrate OpenAPI concepts
servers:
- url: https://example.io/v1
security:
- BasicAuth: []
paths:
/artists:
get:
description: Returns a list of artists
parameters:
# ----- Added line ------------------------------------------
- $ref: '#/components/parameters/PageLimit'
- $ref: '#/components/parameters/PageOffset'
# ---- /Added line ------------------------------------------
responses:
'200':
description: Successfully returned a list of artists
content:
application/json:
schema:
type: array
items:
# ----- Added line --------------------------------
$ref: '#/components/schemas/Artist'
# ---- /Added line --------------------------------
'400':
# ----- Added line ----------------------------------------
$ref: '#/components/responses/400Error'
# ---- /Added line ----------------------------------------
post:
description: Lets a user post a new artist
requestBody:
required: true
content:
application/json:
schema:
# ----- Added line ------------------------------------
$ref: '#/components/schemas/Artist'
# ---- /Added line ------------------------------------
responses:
'200':
description: Successfully created a new artist
'400':
# ----- Added line ----------------------------------------
$ref: '#/components/responses/400Error'
# ---- /Added line ----------------------------------------
/artists/{username}:
get:
description: Obtain information about an artist from his or her unique username
parameters:
- name: username
in: path
required: true
schema:
type: string
responses:
'200':
description: Successfully returned an artist
content:
application/json:
schema:
type: object
properties:
artist_name:
type: string
artist_genre:
type: string
albums_recorded:
type: integer
'400':
# ----- Added line ----------------------------------------
$ref: '#/components/responses/400Error'
# ---- /Added line ----------------------------------------
components:
securitySchemes:
BasicAuth:
type: http
scheme: basic
schemas:
Artist:
type: object
required:
- username
properties:
artist_name:
type: string
artist_genre:
type: string
albums_recorded:
type: integer
username:
type: string
# ----- Added lines ----------------------------------------
parameters:
PageLimit:
name: limit
in: query
description: Limits the number of items on a page
schema:
type: integer
PageOffset:
name: offset
in: query
description: Specifies the page number of the artists to be displayed
schema:
type: integer
responses:
400Error:
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
# ---- /Added lines ----------------------------------------
定義に飛ぶには、$ref
のリンクをクリックしてください。
(自分がクリックした感じ、飛ばなかった気がする...)
サマリ
これで、アーティスト情報を扱うRESTful APIを定義することができました!
今回はOpenAPIの基本をさらっただけですが、他にも色んなことができます。
もっと詳しく知りたい人は、以下の記事を参考にしてみてください!
また、certificationコースもあるので、ぜひ試してみてくださいね!
個人的なまとめ
このTutorialめちゃわかりやすかったです。
ざっとやってみたら、基本的なことがわかったし、
実際にSwagger EditorでドキュメントをHTML表示させられるので良い感じでした。
OpenAPIについて、自分が色々調べて分かったこととしては、以下になります。
- OpenAPIとは、APIの定義を書くときの記述フォーマットのこと
- OpenAPI使って仕様定義するとAPIドキュメントが作れる
- フォーマットが決まってるから、書き方も統一される
- Swagger Editorとか使えばHTMLで見れる
- (補足)その他ツールを使うと、ドキュメントをもとにコード生成とかできたりする
業務で使ったり自分で試したりする過程で、色んなことを調べたので
そこもアウトプットしていけたらなと思います。
Discussion