概要
- OpenAPI Specificationの記載ルールの基本的な部分をまとめる。
- 必須のルートオブジェクト部分だけ深堀りして記載する。
OpenAPIドキュメントについて
- OpenAPIドキュメントの記載はプロジェクトによって固有のルールがあるっぽいので郷に入っては郷に従うほうがいいと思う。
- OpenAPIドキュメントそのものも、「1リクエストにつき1ファイル」のこともあれば「関連するリクエストは1ファイルにまとめる(ユーザー系は1ファイルにまとめる)」等のルールが有ると思う
ルートオブジェクトについて
-
openapi
,info
,paths
のルートオブジェクトは必須となる。とりあえずこの3オブジェクトが記載されていればOpenAPIの仕様書として成り立つ。 - 記載のセオリーとしてはできるだけ
components
オブジェクトにpaths
オブジェクトとsecurity
オブジェクトで使用する内容をなるべく記載し、適宜コンポーネントを呼び出すほうが使いまわしが効いていいのかもしれない。 - もちろん他のオブジェクトも非常に大切だが、とりあえず必須のオブジェクト+
components
とsecurity
オブジェクトの記載方法がわかっていれば大丈夫そう。
ルートオブジェクト名 | 内容 | 必須可否 | |
---|---|---|---|
openapi | 記載するOpenAPIのバージョンを記載 | 必須 | |
info | 記載しようとしているAPI仕様書のメタデータを記載 | 必須 | |
servers | 記載しようとしているAPIがとのような環境で提供されるのかを記載 | ||
tags | 記載しようとしているAPIを分類するためのタグを定義 | ||
paths | 記載しようとしているAPIの最も大切な部分 どのURLにリクエスト送ってどんな内容が帰るのか等 |
必須 | かなり重要だし結構複雑 OpenAPIのメインと行っても過言ではない |
security | 記載しようとしているAPIのセキュリティー要件を定義 | ||
components | OpenAPI内で使用するオブジェクトを定義してコンポーネント化し、使い回せるようにする |
openapiオブジェクトについて
-
openapiオブジェクトでは当該のOpenAPIドキュメントのバージョンを記載する。
-
バージョン情報は下記で確認できる。
-
OpenAPIのバージョンは下記の様に記載する。
openapi.yamlopenapi: "3.0.3"
infoオブジェクトについて
-
当該のOpenAPIドキュメントのメタデータ(概要や詳細)などを記載する。
オブジェクト名 内容 必須可否 備考 title OpenAPIドキュメントそのもののタイトルを定義 必須 例えば「ユーザー系APIドキュメント」とか description OpenAPIドキュメントの詳細内容 Markdownで記載する事ができる termsOfService サービス利用規約のURL APIを公開する際に必要な情報 contact 連絡先情報 APIを公開する際に必要な情報 license ライセンス情報 APIを公開する際に必要な情報
SPDXを参考に記載するとわかりやすいversion OpenAPIドキュメントそのもののバージョン 今あなたが記載しているドキュメントそのものバージョン情報
OpenAPIのバージョン情報ではないので注意 -
必須部分(とopenapiルートオブジェクト)だけ記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0"
tagsオブジェクトについて
-
pathsオブジェクトやその他のオブジェクトで分類分けに使用するタグを予めtagsオブジェクトで定義する事ができる。
-
例えばユーザー系APIに張る
users
タグを定義する場合は下記の様に指定する。(tagsは配列で定義する)キー名 内容 備考 name タグ名 例えば'"users"'等 description タグの説明
pathsオブジェクトについて
-
pathsオブジェクトはOpenAPIドキュメントで記載されるAPI情報のまさにメイン箇所である。
-
情報が多くなるためpathsオブジェクトの階層も深くなる。そのためpathsオブジェクトの説明のみ、階層に分けて実施する。
-
当該のリクエストのURLを指定する。
オブジェクト名 内容 必須可否 備考 当該APIのアクセスURL アクセスURLを ""
で囲って記載する必須 例えば'"/login"'等 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API"
paths → 当該APIのアクセスURLオブジェクトについて
-
paths直下の当該APIのアクセスURLオブジェクトには当該のリクエストのHTTPメソッドオブジェクトが配置される。
オブジェクト名 内容 必須可否 備考 当該APIのHTTPメソッド HTTPメソッドを記載 必須 小文字で当該APIのHTTPメソッドを定義 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login": post:
paths → 当該APIのアクセスURL → HTTPメソッドオブジェクトについて
-
paths直下、当該APIのアクセスURL直下、HTTPメソッドオブジェクトには下記の内容のオブジェクトが配置される。
オブジェクト名 内容 必須可否 備考 summary 当該APIのタイトル description 当該APIの説明 Markdownで記載可能 tags タグの定義 任意のタグをこちらで定義する or
componentルートオブジェクト内で定義したタグを呼び出すdeprecated 当該APIが廃止されているか否か true → 廃止されている
false → 廃止されていないparameter リクエストパラメーターの内容 requestBody リクエストボディーの内容 リクエストボディーで値を渡す場合に記載 response レスポンスの内容 ステータスコードごとに記載する -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameter: requestBody: response:
paths → 当該APIのアクセスURL → HTTP → parametersメソッドオブジェクトについて
-
paths直下、当該APIのアクセスURL直下、HTTP直下、parametersメソッドオブジェクトには下記の内容のキー(配列)が配置される。
キー名 内容 備考 name 渡される値のキー parametersオブジェクトを定義する場合必須 in パラメーターの場所 query, header, path, cookieの中から選んで記載 reequired 必須か否か true → 必須
false → 必須ではない
pathパラメーターの場合、trueにしないとURLが成り立たないので注意schema 渡される値の型を定義 オブジェクトで定義 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: response:
paths → 当該APIのアクセスURL → HTTP → requestBodyメソッドオブジェクトについて
-
paths直下、当該APIのアクセスURL直下、HTTP直下、requestBodyメソッドオブジェクトには下記の内容のキー(配列)が配置される。
オブジェクト名 内容 備考 description リクエストボディーの説明 required 必須か否か true → 必須
false → 必須ではないcontent リクエストボディーの内容 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: description: "ユーザー認証情報" required: true content: response:
paths → 当該APIのアクセスURL → HTTP → requestBody → contentメソッドオブジェクトについて(jsonでオブジェクトの場合)
-
paths直下、当該APIのアクセスURL直下、HTTP直下、requestBody直下、contentメソッドオブジェクトには下記の内容のキー(配列)が配置される。
オブジェクト名 内容 備考 メディアタイプ 当該リクエストボディーのメディアタイプ application/json メディアタイプ → schema 当該リクエストボディーの情報 メディアタイプ → schema → type 当該リクエストボディーの型 メディアタイプ → schema → properties 当該リクエストボディーの型がobjectの場合 メディアタイプ → schema → properties → オブジェクトのキー名{オブジェクト} データオブジェクト内部の型定義と例の記載 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } response:
paths → 当該APIのアクセスURL → HTTP → responseメソッドオブジェクトについて
-
paths直下、当該APIのアクセスURL直下、HTTP直下、responseメソッドオブジェクトには下記の内容が配置される。
オブジェクト名 内容 備考 HTTPステータスコード 想定されるレスポンスのHTTPステータスコード 200や400などの個別指定から2XXや4XXといった200番台、400番台等のレスポンスの指定が可能 HTTPステータスコード → description レスポンスの説明 HTTPステータスコード → content レスポンスの内容 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } response: "2XX": description: "成功処理" content: "4XX": description: "失敗処理(クライアントエラー)" content: "5XX": description: "失敗処理(サーバーエラー)" content:
paths → 当該APIのアクセスURL → HTTP → response → contentメソッドオブジェクトについて
-
paths直下、当該APIのアクセスURL直下、HTTP直下、response直下、contentメソッドオブジェクトには下記の内容が配置される。
オブジェクト名 内容 備考 メディアタイプ 当該レスポンスのメディアタイプ application/json メディアタイプ → schema 当該レスポンスの情報 メディアタイプ → schema → type 当該レスポンスの型 メディアタイプ → schema → properties 当該レスポンスの型がobjectの場合 メディアタイプ → schema → properties → オブジェクトのキー名{オブジェクト} データオブジェクト内部の型定義と例の記載 -
ここまでの必須のルートオブジェクトとpathsオブジェクトを記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } response: "2XX": description: "成功処理" content: application/json: schema: type: object properties: message: { type: string, example: "OK" } "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: type: object properties: message: { type: string, example: "Client NG" } "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: type: object properties: message: { type: string, example: "Server NG" }
componentsオブジェクトについて
-
コンポーネント化したい内容を分類ごとに名前を付けて下記の様に定義する。
オブジェクト名 内容 備考 schemas コンポーネント化するグループ名を記載 schemas → グループ名 コンポーネントのそのものの定義 -
ここまでの内容をcomponentsオブジェクトを用いて記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: { type: string } requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } response: "2XX": description: "成功処理" content: application/json: schema: type: object properties: message: { type: string, example: "OK" } "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: type: object properties: message: { type: string, example: "Client NG" } "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: type: object properties: message: { type: string, example: "Server NG" } components: schemas: RequestHeader: type: string RequestBody: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } OkResponse: type: object properties: message: { type: string, example: "OK" } ClientNgResponse: type: object properties: message: { type: string, example: "Client NG" } ServerNgResponse: type: object properties: message: { type: string, example: "Server NG" }
-
更にここからcomponentsで定義した内容を各schemaで呼び出すと下記の様になる。(
$ref: "#/components/schemas/componentsで定義したグループ名"
でコンポーネントを呼び出す事ができる。)openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: $ref: "#/components/schemas/RequestHeader" requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: $ref: "#/components/schemas/RequestBody" responses: "2XX": description: "成功処理" content: application/json: schema: $ref: "#/components/schemas/OkResponse" "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: $ref: "#/components/schemas/ClientNgResponse" "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: $ref: "#/components/schemas/ServerNgResponse" components: schemas: RequestHeader: type: string RequestBody: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } OkResponse: type: object properties: message: { type: string, example: "OK" } ClientNgResponse: type: object properties: message: { type: string, example: "Client NG" } ServerNgResponse: type: object properties: message: { type: string, example: "Server NG" }
securityオブジェクトについて
-
当該APIのセキュリティー要件を定義する。
-
まずcomponentsに定義を行い、そのコンポーネントを各pathsの記載で呼び出す。もしくはpathsに記載されているすべてのAPIに対してセキュリティー要件を設定し、不要なものを除外する。
-
今回はOAuth2.0のセキュリティー要件を記載してみる。
-
下記の様に記載する。(値は公式ドキュメントの値を設定していますが、各々のの環境にあった内容を記載してください。)
オブジェクト名 内容 必須可否 備考 securitySchemas コンポーネント化するセキュリティー要件のグループ名を記載 securitySchemas → グループ名 セキュリティーそのものの定義 securitySchemas → グループ名 → type セキュリティーのタイプを記載 OAuthとかの認証の種類 securitySchemas → グループ名 → description セキュリティーの説明を記載 securitySchemas → グループ名 → flows OAuthのフローを指定 OAuthのみ、複数存在する
こちらに記載OAuth Flows ObjectsecuritySchemas → グループ名 → flows → authorizationCode OAuthの構成を記載 OAuthのみ securitySchemas → グループ名 → flows → authorizationCode → authorizationUrl 認証URL URL形式のみ受付 必須 OAuthのみ
こちらに記載OAuth Flow ObjectsecuritySchemas → グループ名 → flows → authorizationCode → tokenUrl トークンURL URL形式のみ受付 必須 OAuthのみ securitySchemas → グループ名 → flows → authorizationCode → refreshUrl リフレッシュトークンURL URL形式のみ受付 OAuthのみ securitySchemas → グループ名 → flows → authorizationCode → scopes スコープ名と説明の記載 必須 OAuth2.0のみ -
これまでの記載とセキュリティーの内容をcomponentsに記載すると下記の様になる。
openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: $ref: "#/components/schemas/RequestHeader" requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: $ref: "#/components/schemas/RequestBody" responses: "2XX": description: "成功処理" content: application/json: schema: $ref: "#/components/schemas/OkResponse" "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: $ref: "#/components/schemas/ClientNgResponse" "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: $ref: "#/components/schemas/ServerNgResponse" components: schemas: RequestHeader: type: string RequestBody: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } OkResponse: type: object properties: message: { type: string, example: "OK" } ClientNgResponse: type: object properties: message: { type: string, example: "Client NG" } ServerNgResponse: type: object properties: message: { type: string, example: "Server NG" } securitySchemes: oauth: type: oauth2 description: "OAuth2.0認証" flows: authorizationCode: authorizationUrl: https://example.com/api/oauth/dialog tokenUrl: https://example.com/api/oauth/token scopes: write:pets: modify pets in your account read:pets: read your pets
-
pathsオブジェクト個々にセキュリティーを指定する場合、下記の様になる。(pathsの中のAPIオブジェクトにsecurityオブジェクトを追加して指定、scopeが必要な場合は
[]
の中にスコープ名を記載する。)openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: $ref: "#/components/schemas/RequestHeader" requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: $ref: "#/components/schemas/RequestBody" responses: "2XX": description: "成功処理" content: application/json: schema: $ref: "#/components/schemas/OkResponse" "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: $ref: "#/components/schemas/ClientNgResponse" "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: $ref: "#/components/schemas/ServerNgResponse" security: - oauth2: [] components: schemas: RequestHeader: type: string RequestBody: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } OkResponse: type: object properties: message: { type: string, example: "OK" } ClientNgResponse: type: object properties: message: { type: string, example: "Client NG" } ServerNgResponse: type: object properties: message: { type: string, example: "Server NG" } securitySchemes: oauth: type: oauth2 description: "OAuth2.0認証" flows: authorizationCode: authorizationUrl: https://example.com/api/oauth/dialog tokenUrl: https://example.com/api/oauth/token scopes: write:pets: modify pets in your account read:pets: read your pets
-
pathsオブジェクトすべてににセキュリティーを指定する場合、下記の様になる。(securityルートオブジェクトでセキュリティーコンポーネントを呼び出す。解除したいAPIだけpathsのsecurityオブジェクトに空の配列を指定する。 →
security: []
)openapi.yamlopenapi: "3.0.3" info: title: "ユーザー系API" version: "1.0.0" tags: - name: "users" description: "ユーザー系API" paths: "/login/{userId}": post: summary: "ログイン" description : | - 認証を行いトークンを発行 tags: ["users"] deprecated: false parameters: - name: "userId" in: path required: true schema: $ref: "#/components/schemas/RequestHeader" requestBody: description: "ユーザー認証情報" required: true content: application/json: schema: $ref: "#/components/schemas/RequestBody" responses: "2XX": description: "成功処理" content: application/json: schema: $ref: "#/components/schemas/OkResponse" "4XX": description: "失敗処理(クライアントエラー)" content: application/json: schema: $ref: "#/components/schemas/ClientNgResponse" "5XX": description: "失敗処理(サーバーエラー)" content: application/json: schema: $ref: "#/components/schemas/ServerNgResponse" security: - oauth2: [] components: schemas: RequestHeader: type: string RequestBody: type: object properties: email: { type: string, example: "test@example.com" } password: { type: string, example: "p@ssw0rd" } OkResponse: type: object properties: message: { type: string, example: "OK" } ClientNgResponse: type: object properties: message: { type: string, example: "Client NG" } ServerNgResponse: type: object properties: message: { type: string, example: "Server NG" } securitySchemes: oauth: type: oauth2 description: "OAuth2.0認証" flows: authorizationCode: authorizationUrl: https://example.com/api/oauth/dialog tokenUrl: https://example.com/api/oauth/token scopes: write:pets: modify pets in your account read:pets: read your pets