REST APIを設計する機会が増えてきたこともあり、Open APIを使って設計を試しにやってみました。
作成するAPIネタ
REST APIを設計するにあたり、APIのネタは「TODO」に関するものにしました。
本当に必要最低限の情報だけとします。
よって、以下のAPIを設計します。
- TODOの作成
- TODOの更新
- TODOの取得
- TODOの削除
OpenAPIとは何ですか
REST APIを設計する前に、OpenAPIとは何かを簡単に書きます。
OpenAPI仕様は、REST APIのためのAPI記述フォーマット。
OpenAPIファイルは、以下の記述をすることが可能です。
・利用可能なエンドポイントと各エンドポイントに対する操作
・各操作パラメータの入出力の定義
・認証方法
・情報、ライセンス、ユーザやその他の情報
API仕様は、YAMLかJSONで記述することができる。
ツールとしては、Swagger Editor、Swagger UI、Swagger Codegenがありますが、そのほかにもOpenAPIでの記法をサポートしてくれるツール群は存在します。
Swagger Editorを起動してみる
OpenAPIでREST APIを設計するためにSwagger Editorを使って作業を進めることにします。
Swagger Editorを使うにはDockerから起動するかHTTPサーバを起動するかのどちらかだと思います。
(他のやり方があるかもしれませんが、私が知る限りは2パターン)
Dockerで起動する
Dockerを使ってSwagger Editorを起動する場合は以下の手順で実行します。
docker pull swaggerapi/swagger-editor docker run -d -p 80:8080 swaggerapi/swagger-editor
HTTPサーバで起動する
HTTPサーバで起動する場合、私はNode.jsをインストールしhttp-serverを起動して使用しています。
git clone https://github.com/swagger-api/swagger-editor.git
npm install http-server
cd swagger-editor
../node_module/.bin/http-server
REST APIを設計してみた
先ほどTODOに関する操作のREST APIを設計してみました。
OpenAPIの記法などはOpenAPIのページを見るのが一番良いと思います。
APIに関する情報を記載するinfoセクションなどの記載内容がよく分かってないので、ちゃんと調べようと思いました。
実際のAPIの部分については、最初はどのように記述したら良いか分からなかったのですが、Swagger Editor が記法に誤りがあればお知らせしてくれるので、すぐに記述誤りに気づくことができます。
また、なぜ間違っているのかの情報とどこの行番号に間違いが発生しているのか分かります。
openapi: 3.0.3 info: title: TODO api description: TODOを操作するためのAPI termsOfService: http://example.com/terms/ contact: name: 窓口担当 url: http://www.todomng.com email: todommng@example.com license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html version: 1.0.0 servers: - url: http://localhost description: todo api server paths: /todo: post: tags: - TODOの登録 description: TODOを登録する requestBody: content: application/json: schema: $ref: '#/components/schemas/TodoInformation' responses: '201': description: TODOの登録完了 content: application/json: schema: $ref: '#/components/schemas/TodoId' '400': description: リクエスト不正 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '500': description: システム内で異常が発生し正常にリクエストが処理できなかった場合 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' get: tags: - TODOの取得 description: TODOの一覧を取得する parameters: - in: query name: todo_id schema: type: integer format: int32 - in: query name: offset schema: type: integer format: int32 - in: query name: limit schema: type: integer format: int32 responses: '200': description: TODO情報 content: application/json: schema: type: array items: $ref: '#/components/schemas/TodoInformation' '400': description: リクエスト不正 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '500': description: システム内で異常が発生し正常にリクエストが処理できなかった場合 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '/todo/{todo_id}': patch: parameters: - in: path required: true name: todo_id schema: type: integer format: int32 tags: - TODOを更新 description: TODOを更新する requestBody: content: application/json: schema: $ref: '#/components/schemas/TodoInformation' responses: '204': description: TODO更新成功 '400': description: リクエスト不正 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '404': description: 更新対象のリソースが存在しない content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '500': description: システム内で異常が発生し正常にリクエストが処理できなかった場合 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' delete: parameters: - in: path required: true name: todo_id schema: type: integer format: int32 tags: - TODOを削除 description: TODOを削除する responses: '200': description: TODOの削除成功 '400': description: リクエスト不正 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '404': description: 削除対象のリソースが存在しない content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' '500': description: システム内で異常が発生し正常にリクエストが処理できなかった場合 content: application/json: schema: $ref: '#/components/schemas/TodoOpeError' components: schemas: TodoInformation: type: object properties: title: type: string minLength: 1 maxLength: 100 description: TODOの件名 example: todo追加 detail: type: string maxLength: 300 description: TODOの詳細 example: todoを追加します progress: type: integer format: int32 minimum: 0 maximum: 100 description: TODOの進捗率 example: 50 start_date: type: string format: date description: 開始予定日 end_date: type: string format: date description: 終了予定日 required: - title - progress TodoId: type: object properties: todo_id: type: integer format: int32 description: TODOの登録番号 example: 1 TodoOpeError: type: object properties: error_code: type: string description: エラーコード example: 0000001 error_message: type: string description: エラーメッセージ example: error message.
まとめ
REST APIの設計にエクセルを使用していたこともありましたが、エクセルだと記法の誤りを検出するには、人頼りになるところがあるため、設計バグを盛り込んでしまう可能性があります。
それに対し、OpenAPIによる設計かつSwagger Editorを活用することで記法の誤りは事前に防ぐことができます。
記法の誤りを事前に検出できれば、バグの盛り込みを未然に防ぐことが可能です。
そのため、REST APIを設計する際は必ずOpenAPIで定義するようにしようと思いました。
また、設計するにはどのように定義すれば良いのか調べる時間も必要のため、最初の設計時には多少の作業コストがかかることを事前に見積もっておくことが大事だと思います。
最後に
今回、OpenAPIは3.0.3を指定してましたが、3.1.0がリリースされてました。
3.1.0でどのような記述が可能になったのか、確認したい。
3.1.0の紹介がYoutubeにあがっている。
www.youtube.com
ちゃんとステータスコードも設計しよう。
developer.ntt.com