プロダクトを作っていく時に、仕様に関する情報をしっかり作っておくことで、新しくプロジェクトに加わる人に、細かく仕様を説明する必要がなくなります。さらにフロントエンドとバックエンドが共通の仕様を見ることで、認識の齟齬が少なくなり開発効率を最大化することができます。そのためにもOpenAPIを使用してAPIの設計書を作成しておきます。
OpenAPIを使用するメリットは以下が挙げられます。
- APIを指定のフォーマットで規定できる
- ファイルがAPIドキュメントになる
- API定義からサーバやクライアントのコード生成ができる
OpenAPIとは
OpenAPIは、Web APIの仕様を形式的に記述するためのフォーマットのことです。APIの設計書みたいなものです。
OpenAPI generator
openapi-generatorはOpenAPI Specificationをベースにして様々なクライアントやサーバのコードを自動で生成できます。
基本的な言語には対応しています。
今回はNuxtで使用するであろうtypescript-axios
のコードを自動で生成します。
作成手順
Nuxtを使用している場合、予めsrc/types
を作成しておいてください。
openapi-generatorが自動でファイルを生成して保存する先をsrc/types
にするためです。
APIの定義ファイルの作成
まず、APIの定義するためのopenapi.yml
の内容は以下のようにして作成してください。
openapi.yml
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
こちらの内容に関しては、こちらを参考に作成しています。
そして、openapi.yml
と同じディレクトリにdocker-compose.yml
を作成します。
docker-compose.yml
version: '3'
services:
# https://github.com/openapitools/openapi-generator-cli
openapi-generator:
image: openapitools/openapi-generator-cli
volumes:
- ./:/app
command: generate -g typescript-axios -i /app/openapi.yml -o /app/src/types/typescript-axios
openapi-generatorのDocker Imageがすでに用意されているのでそれを使用しています。
以下コマンドを実行することでsrc/types
以下にtypescript-axios
というフォルダが自動で生成され、その中に型のファイルが自動で生成されます。
$ docker-compose up -d openapi-generator
Swagger UI
API仕様の自動作成までできたので、次はドキュメントを作成していきます。
ドキュメント作成にはswagger-uiを使用します。
個人的にデザインがあまり好きではないですが笑。
こちらもすでにDocker Imageが用意されているのでそれを使用します。
docker-compose.yml
に以下の内容を追記してください。
version: '3'
services:
# https://swagger.io/tools/swagger-ui/
swagger-ui:
image: swaggerapi/swagger-ui
volumes:
- ./openapi.yml:/app/openapi.yml
environment:
SWAGGER_JSON: /app/openapi.yml
ports:
- 8080:8080
または、以下でも簡単に使うことができます。
$ docker run --rm -p 8080:8080 -e SWAGGER_JSON=/app/openapi.yml -v ${PWD}:/app swaggerapi/swagger-ui
http://localhost:8080 にアクセスすると見れるようになっていると思います。
スタブサーバを作成
開発をしていると簡単にAPIを試したくなる時があります。そのために、openapi.yamlのAPIをモックするためのスタブサーバを生成します。
今回はprismを使用します。
Stoplightが開発しており、StoplightはStoplight Studio
というAPI仕様を記載するためのGUIエディタを作成しています。
これがとても使いやすく簡単に素早くAPI仕様を記述することができます。Swagger Editorはもう必要ないと思います。
docker-compose.ymlに以下を追記
version: '3'
services:
# https://stoplight.io/p/docs/gh/stoplightio/prism
mock-api:
image: stoplight/prism
volumes:
- ./openapi.yml:/app/openapi.yml
ports:
- 4010:4010
# -dをつけることでランダムなデータが返ってくる
command: mock -h 0.0.0.0 -d /app/openapi.yml
そして以下のコマンドを実行
$ docker-compose up -d mock-api
スタブサーバーが立ち上がったかどうか確認するにはcurl
でURLを叩いてみましょう。
$ curl -s -X GET "http://localhost:4010/pets"
ランダムなデータが返ってきたら成功です。
実際にNuxtで使用する場合は、以下のようになります。
const response = await $axios.get('http://localhost:4010/pets')
console.log(response)
最終的なdocker-compose.ymlは以下になります。
version: '3'
services:
# https://github.com/openapitools/openapi-generator-cli
openapi-generator:
image: openapitools/openapi-generator-cli
volumes:
- ./:/app
command: generate -g typescript-axios -i /app/openapi.yml -o /app/src/types/typescript-axios
# https://swagger.io/tools/swagger-ui/
swagger-ui:
image: swaggerapi/swagger-ui
volumes:
- ./openapi.yml:/app/openapi.yml
environment:
SWAGGER_JSON: /app/openapi.yml
ports:
- 8080:8080
# https://stoplight.io/p/docs/gh/stoplightio/prism
mock-api:
image: stoplight/prism
volumes:
- ./openapi.yml:/app/openapi.yml
ports:
- 4010:4010
# -dをつけることでランダムなデータが返ってくる
command: mock -h 0.0.0.0 -d /app/openapi.yml
スキーマの分解
APIが増えていくにつれてopenapi.yml
が肥大化していくのが容易に想像がつきます。
そのためにスキーマの分解が必要です。
OpenAPI generatorの方はうまく分解したファイルを参照できるのですが、swagger UIでは参照がされない(そういう仕様なのかな)ので、現在調査中です。
参考
※現在調査中なので、完了次第追記します。
まとめ
導入してみると結構開発が楽になるので是非使ってみてください。
参考
OpenAPIとTypeScriptで作る!チーム開発に適したWebアプリケーションの作り方
OpenAPI generatorを試してみる
俺的【OAS】との向き合い方 (爆速でOpenAPIと友達になろう)
本当に使ってよかったOpenAPI (Swagger) ツール
OpenAPI Generator + TypeScript で始める自動生成の型に守られた豊かなクライアント生活
OpenAPI GeneratorでRESTful APIの定義書から色々自動生成する