OpenAPIを棚卸しする(3.0.x)
はじめに
社内で技術的な共有として、それなりに業務経験のある OpenAPI を題材にしてみようと考えた時に、
スライドを作成する前に、用語などを整理するために2021年に記事を書き起こした。
関連用語
| 単語 | 説明 |
|---|---|
| OpenAPI |
OpenAPI Specification に従った各種ツール群などの通称。記載された json/yaml もしくは Swagger-UI のことを一般的に指すと思う。 |
| OpenAPI Specification | OpenAPIの仕様です。APIの記述形式を指しています。この記述形式に従って定義書を書く事で、仕様に従った各種ツールと連携できる。略すと OAS らしい。 |
| Swagger | OpenAPIの前身。 Swagger を取り巻いていた後述のツールなどは現在もメンテされている。 |
| Swagger Editor |
OpenAPI Specification に従ったファイルをウェブブラウザで編集できるエディター。 docker でも配られていたりする。 |
| Swagger UI |
OpenAPI Specification に従ったファイルをウェブブラウザで描画するツール。 docker でも配られていたりする。 |
| OpenAPI Generator |
OpenAPI Specification に従ったファイルから色々生成するツール。 |
| Web API | Web技術を用いて提供されているAPI |
| RESTful API | RESTに従って設計された Web API 。 OpenAPI Specification は RESTful API を対象としている。 |
| (Web)API仕様書 | APIの仕様書。 |
| エンドポイント |
URI と HttpMethod の組み合わせ。 |
| オープンAPI | 公開されているAPIのこと。プライベートの逆。パブリックAPIとも呼ぶ。 |
| (API)スキーマ | どこにどんなリクエストを送るとどんなレスポンスが返ってくるかの取り決めのこと。 |
| スキーマ駆動 | APIの利用者と提供者が一緒になってスキーマの設計を行い、スキーマありきで開発をすすめる手法のこと。 |
OpenAPIってなにを解決するツールなの?
私達が抱える課題
- API仕様書が
在るべきところにない/集約していない/見つけられない - API仕様書のフォーマットが揃っていない(≒読み方をフォーマット毎に理解しないといけない)
- APIを一発実行しようとする時にパラメータのサンプルがない、実行できるデータの準備が必要
- API仕様書と実装が乖離している、メンテナンスが追いついていない
😆 「商品情報を引っ張りたいんだけど、商品情報取得APIみたいなのあるかな?仕様書どこだろう」
😅 「仕様書がWordファイルなんだけど、最終更新が5年前、、、この仕様書はマスタなのだろうか、最新なのだろうか」
😓 「APIを一発叩いてみようと思うけど、パラメータ指定するのめんどくさいな。」
😢 「別のAPI叩こうとしたら仕様書のフォーマット違ってて辛い。」
😩 「APIを叩いてみたら仕様書通りのレスポンスが返ってこない。」
OpenAPIはなにを実現/解決できるのか
OpenAPI Specification
- 定義ファイルの中身は
json/yamlなので、メモ帳/テキストエディターで閲覧/編集可能
※OpenAPIは各種支援ツールが豊富なのでVS Codeなどのプラグインも有
※Swagger Editorでpreviewしながら編集も可能。 - バージョン管理が容易、編集/変更履歴/仕様変更/変更差分などが追跡しやすい
- チーム内で標準化しやすい。
※OpenAPI Specificationでネットで調べると記述方法がhitする - 繰り返し出現する要素を共通化することにより仕様書の記述コストを下げることが可能
※ difinitionsに集約することで、一箇所修正すれば使用箇所は全て反映される
Swagger UI
- 定義した
json/yamlがヒューマンリーダブルに描画される - パラメータが
example valueに従って自動生成されるのでAPIの一発実行もフランクに行える - API実行ツールを内包している
※ 中身はcurl - httpで公開できるので、ブラウザで遠隔からアクセスできる
※ 共有ファイルサーバなどでも実現可能ではあるが。。。。
定義ファイルからの自動生成
- 自動化テストの作成補助
- モックサーバの用意
※ モックを用意すれば、フロント側の開発が着手できる - 実装(プログラム)の一部自動生成
※ 仕様書と実装のインターフェースが完全に揃う
※ 提供/利用側もどちらも対象 - PostmanなどのAPIクライアントツールでのテストリクエストimport機能
※ めんどくさいテストもこの機能で負担を軽減できそう
※ APIクライアントツールのテストリクエストをエクスポートして配ればなお良し
ツールだけで解決できないこと
- API仕様書を
在るべきところにおく
※ 目につきやすい所にSwagger-UIのリンク貼っておこう、布教しよう - APIをサンプルで用意されているパラメータで叩いても正常系が返ってこない
※ サンプルを工夫するか、データに依存しないように実装自体をいじってしまおう - API仕様書からプログラムの全自動生成
※ NoCodeとまでは言えない、API仕様書と実装が乖離しないように絶えずメンテが必要
類似ツール
API BlueprintCarteRAML
Swagger-UIで見てみよう
早速書いてみよう!よりも先に書いた後どうなるかをさらっと記載する。
閲覧する人
- APIを提供する側
- APIを利用する側
まずはAPI仕様書を参照する読者を考えてみる。
もちろん開発者(提供者)自身が書いて、読み返すことが考えられる。
APIの利用者が読むわけで、利用パターンは
- バックエンド -> バックエンド
- フロントエンド -> バックエンド
が考えられ、バックエンドエンジニアとフロントエンドエンドエンジニアが存在する。
APIを外部公開して収益を挙げる場合、販売する営業さんも見るかもしれない。
となると、開発に関わるエンジニア以外も見るケースがあるかもしれない。
OpenAPIの構成
sample(petstore)を例に大きな要素を箇条書きする。
※ OpenAPI 3.0の仕様で記載する
Explore
入力欄に描画したい json/yaml ファイルのパスを指定し、
Exploreボタン を押下することでAPI仕様書を切り替えることができる。
正直使わない。
info , servers , security
描画中のAPI仕様書の概要、サーバー情報などが表示される。
またAPIアクセスに認証などが必要だった場合は、 Authorizeボタン から情報を入力すると、
API実行時に自動でリクエストヘッダなどに値を設定してくれる。
tags , paths
tag -> path の順でソートされており、
tag -> description(説明) , operation/path -> summary(概要) を1行で出力している。
tag は エンドポイント群をグルーピングしており、意味のある塊として扱っている。
APIは operation/path で1行であり、 operation(HTTP method) 毎に色が分けられている。
※ DELETEは赤色で、触ったらいけない感を演出しているように見える
operation/path を展開すると、 description , Parameters , Responses で分かれていて、 Try it outボタン がある。
Try it outボタン を押下すると入力欄が活性化され、
さらに Executeボタン を押下することでAPIに入力値を送出することができる。
Models
API仕様書内で構造化したオブジェクトの一覧を並べている。
200以外のレスポンスなどは、実装時にフレームワークなどで統一したものを返却するので、
そういった共通のオブジェクトが並んでいたりする。
OpenAPI Specificationに従って書いてみる
json/yamlで記載する。どちらもたいして優位性は変わらない。
初心者はyaml推奨。Swagger-Editorのサンプルがyamlなので。
$ref を使用すると、ファイルを参照させることができ、ファイル単位で切り出せたりできる。
エディター
- VS Code (Swagger Viewer)
- Swagger Editor
- Stoplight Studio
OpenAPIの構成
仕様書として必要最低限のものを並べてみる。
公式の並び順ではなく、
- info
- servers
- tags
- paths
- components
の順に並べる。
API情報
APIの情報を定義するフィールド。
| property | value | required | array |
|---|---|---|---|
| openapi | OpenAPI Specification のバージョン | ○ | |
| info | APIの情報 詳細 | ○ | |
| [Info].title | APIの名前 | ○ | |
| [Info].description | APIの説明 | ||
| [Info].version | APIのバージョン | ○ |
<details><summary>コード</summary><div>
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
</div></details>
サーバー情報
サーバーの情報を定義するフィールド。
servers は必須ではないのでなくてもいい。
| property | value | required | array |
|---|---|---|---|
| servers | APIのサーバー情報 環境毎に定義したりする 詳細 | ○ | |
| [Server].url | APIのURL | ○ | |
| [Server].description | URLの説明 | ○ |
<details><summary>コード</summary><div>
servers:
- url: http://petstore.swagger.io/v1
</div></details>
Tag情報
タグの情報を定義するフィールド。
エンドポイントをグルーピングし、意味のある塊として扱うために定義する。
| property | value | required | array |
|---|---|---|---|
| tags | タグの情報 詳細 | ○ | |
| [Tag].name | タグの名前 | ○ | |
| [Tag].description | タグの説明 |
エンドポイント
エンドポイントの情報を定義するフィールド。
これがメイン。
| property | value | required | array |
|---|---|---|---|
| paths | エンドポイントの情報 詳細 | ○ | |
| [Path].parameters | パス内のパラメータなどを定義する [Path].[Operation]配下まで適用される 詳細 | ○ | |
| [Path].[Operation] | HttpMethod get , post , put , patch , delete などのいずれか 詳細
|
○ | |
| [Path].[Operation].tags | エンドポイントの所属するタグ | ○ | |
| [Path].[Operation].summary | エンドポイントの概要 Swagger UI では1行で表示される |
||
| [Path].[Operation].description | エンドポイントの説明 | ||
| [Path].[Operation].operationId | エンドポイントのユニークID | ||
| [Path].[Operation].parameters | エンドポイントのパラメータなどを定義する 詳細 | ○ | |
| [Path].[Operation].requestBody | エンドポイントのリクエストボディ 詳細 | ||
| [Path].[Operation].responses | エンドポイントのレスポンス [HTTP Status Code]毎に定義する 詳細 | ○ |
| property | value | required | array |
|---|---|---|---|
| [Parameter].name | パラメータの物理名 | ○ | |
| [Parameter].in | パラメータの種別 query , header , path , cookie のいずれか |
○ | |
| [Parameter].description | パラメータの説明 | ○ | |
| [Parameter].required | パラメータが必須か否か true , false のいずれか |
| property | value | required | array |
|---|---|---|---|
| [RequestBody].description | リクエストボディの説明 | ||
| [RequestBody].required | リクエストボディが必須か否か true , false のいずれか |
||
| [RequestBody].content | リクエストボディの内容 詳細 | ○ | |
| [RequestBody].[MediaType].schema | 詳細 |
| property | value | required | array |
|---|---|---|---|
| [Response].description | レスポンスの説明 | ○ | |
| [Response].content | レスポンスの内容 詳細 | ○ | |
| [Response].[MediaType].schema | 詳細 |
共通オブジェクト
共通のオブジェクトなどを切り出して定義するフィールド。
200 OK 以外の 400 Bad Request などの汎用的に使いまわせるオブジェクトなどを定義する。
$ref を使って参照させる。
| property | value | required | array |
|---|---|---|---|
| components | 詳細 | ||
| component.schemas | 詳細 | ||
| component.responses | 詳細 | ||
| component.parameters | 詳細 | ||
| component.requestBodies | 詳細 | ||
| component.headers | 詳細 |
てっとり早く書いて公開するためには?
OpenAPI Specification の version3.0 基準で書かれている/公開されているものの json/yaml を引っ張ってきて、
参考に書き換えていけば良さそう。
sample(petstore)は version2.0 なので、このまま使うと古い仕様になってしまう。
Githubに公開されているversion3.0は参考にできそう。
工夫して書こう
-
descriptionにHTMLを使って説明をリッチにする - プロパティの定義(型/length/定数/文字種別)は堅牢に
<details><summary>背景</summary><div>
API仕様書に処理の詳細を書く必要は無いが、1行だけの説明だと味気ない。
データに依存するような仕様が存在した場合は、是非書いておこう。
テーブル表記などはHTMLで表現できる。
永続化されている/するパラメータについては、リソースの設定に依存される。
例えば、MySQLの int(unsigned) は 0~4294967295 の範囲。
範囲外のものは永続化できないし、そもそも文字列などは指定できない。
この場合、API仕様書では
type: integer
minimum: 0
maximum: 4294967295
のように定義できる。
リソースの仕様も設計時に事前の確認が必要そう。
氏名(カナ)を登録/更新などする際は、
type: string
pattern: '[ァ-ヶ]*'
のように定義できる。
</div></details>
OpenAPIを使ったWebAPI開発について
どんな感じで開発していくか考えてみた。
- OpenAPIをチームで書くための準備をする
※ チームがコミットできるようにGithub/Gitlabにリポジトリを用意する
※ エンドポイント以外の骨組みを定義し終え、Swagger Editorでエラーがでない状態にしておく
※Swagger UIサーバーをたてる(Gitlabだと内包しているので別途用意する必要なし) - 設計を進める/OpenAPIを書く/レビューする/OpenAPIを更新する
- OpenAPIから色々自動生成できるように技術調査/用意をすすめる
※ モックサーバの用意
※ 実装(プログラム)の一部自動生成 - OpenAPIの完成
- モックサーバの準備
※ サーバの用意
※ OpenAPIが更新された場合、モックサーバ側のファイルの更新をどうするかの確認 - WebAPI実装の準備
※ OpenAPIが更新された場合、自動生成ファイルも更新できるかなどの確認 - WebAPI実装の着手/OpenAPIの修正
※ 実装がすすんだ際の仕様変更/方針の反映
※ OpenAPIが更新された場合の連絡/周知などの徹底 - WebAPI実装の完了/テスト実施完了
※ APIクライアントツールでOpenAPI取り込み
※ APIクライアントツールでテスト実施
こんな感じになるかなぁと。
色々とCIに組み込めたりすると、最初は準備が大変だけど保守は楽になるかなと思う。
Discussion