概要
APIの検証、ドキュメント化およびドキュメント化にSwaggerを使っているプロダクトが多いかと思います
今回はDockerを使ってSwagger用の環境を構築する方法について解説していきます
前提
- 今回はバックエンドのフレームワークにDjangoを使用します
- 後述するCORSの設定に関してましてはDjangoの設定ファイル内の記載方法を解説していますがSwaggerのドキュメントの記載方法は使用しているフレームワークが違っていても参考になるかと思います
- Dockerとdocker-composeに関する基礎的な知識を有していること
ファイル構成
tree
・
├── application # アプリケーションを格納する専用フォルダ
│ └── project
│ └── settings.py # Djangoの設定ファイル
├── doc
│ └── openapi.yml
└── docker-compose.yml
Swagger用のコンテナの設定
今回はdocker-compose.ymlを使ってSwaggerのコンテナを作成します
# swaggerの設定
doc:
image: swaggerapi/swagger-ui
container_name: doc
# 後述するdocフォルダ内のAPI仕様書(openapi.yml)を/usr/share/nginx/html/openapi.ymlへマウントする
volumes:
- ./doc/openapi.yml:/usr/share/nginx/html/openapi.yml
# openapi.ymlを指定
environment:
API_URL: openapi.yml
ports:
- 9000:8080
API仕様書(openapi.yml)の作成
openapi.ymlを作成します
# https://swagger.io/specification/
# openapiのバージョン。今回は
openapi: 3.1.0
# APIに関するメタデータ
info:
# プロジェクト名を記載
title: project
description: |-
# プロジェクトの詳細
version: 1.0.0
# Djangoは8000ポートを使用しているので今回は以下のように指定
servers:
- url: http://localhost:8000/
Corsの設定
アプリケーション側とSwagger側のオリジンが違うためSwaggerのコンテナからAPIへリクエストを送るとCORSエラーが発生してしまいます
そのため、Swagger側のオリジンを許可するようCORSの設定を行います
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"application.apps.ApplicationConfig",
# corsheadersをINSTALLED_APPSに追加
"corsheaders",
]
# 自身以外のオリジンのHTTPリクエスト内にクッキーを含めることを許可する
CORS_ALLOW_CREDENTIALS = True
# アクセスを許可したいURL(アクセス元)を追加
CORS_ALLOWED_ORIGINS = "localhost:9000"
# プリフライト(事前リクエスト)の設定
# 30分だけ許可
CORS_PREFLIGHT_MAX_AGE = 60 * 30
以下のような画面が表示されたら成功です
実際にAPI仕様書を作成してみよう!
ここから以下のAPIのドキュメントを作成していきます
- ログイン
- ユーザ
- 一覧表示
- 詳細
ログイン
# タグ
tags:
- name: login
description: ログインAPI
externalDocs:
description: ログインについて
url: https://qiita.com/shun198/items/067e122bb291fed2c839
# APIのパス
/api/login/:
post:
tags:
- login
summary: ログインAPI
description: アプリケーションにログインする
requestBody:
content:
application/json:
schema:
type: object
properties:
employee_number:
type: string
description: 社員番号
example: "00000001"
password:
type: string
description: パスワード
example: "test"
required:
- "employee_number"
- "password"
responses:
# 成功した時と失敗した時など複数以上のResponse例を記載できる
"200":
description: ログインに成功
content:
application/json:
schema:
type: object
example:
role: "MANAGEMENT"
"400":
description: ログインに失敗
content:
application/json:
schema:
type: object
example:
msg: "社員番号またはパスワードが間違っています"
/api/login/
に以下に表示させたい項目を記載していきます
RequestとResponseのschemaの下に必要な項目の詳細や入力する値のデフォルト値などを設定できます
また、タグをつけることでSwagger内にAPIの仕様の詳細のリンクを貼ったりできます
認証の設定
ログイン機能を実装した際は認証の設定をSwagger側でする必要があります
今回はBasic認証の設定方法を記載します
openapi: 3.1.0
info:
title: project
description: |-
version: 1.0.0
servers:
- url: http://localhost:8000/
# basic認証の設定
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
security:
- basicAuth: []
securityに認証方法を記載することで一度認証に成功すれば、認証が必要なAPI全てにアクセスできるようになります
ユーザのAPI
ここからユーザAPIの
- 一覧表示
- 詳細
の設定方法について解説していきます
一覧表示
/api/users/:
get:
tags:
- users
summary: システムユーザのAPI
description: システムユーザを一覧表示する
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
properties:
id:
type: string
description: UUID
employee_number:
type: string
description: 社員番号
username:
type: string
description: ユーザ名
email:
type: string
description: メールアドレス
role:
type: int
description: ロール
examples:
user_example:
value:
- id: "00000000-0000-0000-0000-000000000001"
employee_number: "00000001"
username: "test01"
email: "test01@example.com"
role: 0
- id: "00000000-0000-0000-0000-000000000002"
employee_number: "00000002"
username: "test02"
email: "test02@example.com"
role: 1
- id: "00000000-0000-0000-0000-000000000003"
employee_number: "00000003"
username: "test03"
email: "test03@example.com"
role: 2
- id: "00000000-0000-0000-0000-000000000004"
employee_number: "00000004"
username: "test04"
email: "test04@example.com"
role: 0
一覧表示など複数以上のJSONデータを表示させるときは以下のようにexamplesの下に値を記載していきます
以下のように表示されたら成功です
詳細
今回は/api/users/{id}/を例に記載します
IDをなどのパラメータを指定するときはparametersに記載することでデフォルト値をあらかじめ入れることができます
# APIのパス内にIDがあるときは以下のように{id}と記載
/api/users/{id}/:
get:
tags:
- users
summary: システムユーザのAPI
description: 該当するUUIDのシステムユーザを取得する
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
example:
id: "00000000-0000-0000-0000-000000000001"
employee_number: "00000001"
username: "test01"
email: "test01@example.com"
role: 0
parameters:
- name: id
in: path
required: true
description: 取得したいシステムユーザのUUID
schema:
type: string
example: "00000000-0000-0000-0000-000000000001"
完成
ユーザのAPIのCRUD操作もまとめると以下のようになります
# https://swagger.io/specification/
openapi: 3.1.0
info:
title: project
description: |-
version: 1.0.0
servers:
- url: http://localhost:8000/
# basic認証の設定
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
security:
- basicAuth: []
tags:
- name: login
description: ログインAPI
externalDocs:
description: ログインについて
url: https://qiita.com/shun198/items/067e122bb291fed2c839
- name: users
description: システムユーザ関連のAPI
paths:
/api/login/:
post:
tags:
- login
summary: ログインAPI
description: アプリケーションにログインする
requestBody:
content:
application/json:
schema:
type: object
properties:
employee_number:
type: string
description: 社員番号
example: "00000001"
password:
type: string
description: パスワード
example: "test"
required:
- "employee_number"
- "password"
responses:
"200":
description: ログインに成功
content:
application/json:
schema:
type: object
example:
role: "MANAGEMENT"
"400":
description: ログインに失敗
content:
application/json:
schema:
type: object
example:
msg: "社員番号またはパスワードが間違っています"
/api/users/:
get:
tags:
- users
summary: システムユーザのAPI
description: システムユーザを一覧表示する
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
properties:
id:
type: string
description: UUID
employee_number:
type: string
description: 社員番号
username:
type: string
description: ユーザ名
email:
type: string
description: メールアドレス
role:
type: int
description: ロール
examples:
user_example:
value:
- id: "00000000-0000-0000-0000-000000000001"
employee_number: "00000001"
username: "test01"
email: "test01@example.com"
role: 0
- id: "00000000-0000-0000-0000-000000000002"
employee_number: "00000002"
username: "test02"
email: "test02@example.com"
role: 1
- id: "00000000-0000-0000-0000-000000000003"
employee_number: "00000003"
username: "test03"
email: "test03@example.com"
role: 2
- id: "00000000-0000-0000-0000-000000000004"
employee_number: "00000004"
username: "test04"
email: "test04@example.com"
role: 0
post:
tags:
- users
summary: システムユーザのAPI
description: システムユーザを登録する
requestBody:
content:
application/json:
schema:
type: object
properties:
employee_number:
type: string
description: 社員番号
example: "00000005"
username:
type: string
description: ユーザ名
example: "test05"
email:
type: string
description: メールアドレス
example: "test05@example.com"
role:
type: int
description: ユーザ名
example: 0
required:
- "employee_number"
- "username"
- "email"
- "role"
responses:
'201':
description: 成功
content:
application/json:
schema:
type: object
example:
id: "Random UUID"
employee_number: "00000005"
username: "test05"
email: "test05@example.com"
role: 0
/api/users/{id}/:
get:
tags:
- users
summary: システムユーザのAPI
description: 該当するUUIDのシステムユーザを取得する
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
example:
id: "00000000-0000-0000-0000-000000000001"
employee_number: "00000001"
username: "test01"
email: "test01@example.com"
role: 0
parameters:
- name: id
in: path
required: true
description: 取得したいシステムユーザのUUID
schema:
type: string
example: "00000000-0000-0000-0000-000000000001"
put:
tags:
- users
summary: システムユーザのAPI
description: 該当するUUIDのシステムユーザを更新する
requestBody:
content:
application/json:
schema:
type: object
properties:
employee_number:
type: string
description: 社員番号
example: "00000005"
username:
type: string
description: ユーザ名
example: "test05"
email:
type: string
description: メールアドレス
example: "test05@example.com"
role:
type: int
description: ユーザ名
example: 0
required:
- "employee_number"
- "username"
- "email"
- "role"
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
example:
id: "00000000-0000-0000-0000-000000000004"
employee_number: "00000004"
username: "test04"
email: "test04@example.com"
role: 0
parameters:
- name: id
in: path
required: true
description: 更新したいシステムユーザのUUID
schema:
type: string
example: "00000000-0000-0000-0000-000000000004"
patch:
tags:
- users
summary: システムユーザのAPI
description: 該当するUUIDのシステムユーザを一部更新する
requestBody:
content:
application/json:
schema:
type: object
properties:
employee_number:
type: string
description: 社員番号
example: "00000005"
username:
type: string
description: ユーザ名
example: "test05"
email:
type: string
description: メールアドレス
example: "test05@example.com"
role:
type: int
description: ユーザ名
example: 0
required:
- "employee_number"
- "password"
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
example:
id: "00000000-0000-0000-0000-000000000004"
employee_number: "00000004"
username: "test04"
email: "test04@example.com"
role: 0
parameters:
- name: id
in: path
required: true
description: 一部更新したいシステムユーザのUUID
schema:
type: string
example: "00000000-0000-0000-0000-000000000004"
delete:
tags:
- users
summary: システムユーザのAPI
description: 該当するUUIDのシステムユーザを削除する
responses:
'204':
description: 成功
content:
application/json:
schema:
type: object
parameters:
- name: id
in: path
required: true
description: 削除したいシステムユーザのUUID
schema:
type: string
example: "00000000-0000-0000-0000-000000000004"
まとめ
ドキュメント作成に必要な項目を一通り記載してみました
- Dockerでローカルを汚さない
- GitHubでAPI仕様書をバージョン管理できる
- SwaggerでAPIの検証ができる
ことに大きな魅力を感じますね
今後は
- ファイルのアップロード
- クエリパラメータ
などの設定方法も追記していきたいと思います
参考