OpenAPI による REST APIの設計
こんにちは。NOBORIの水澤です。
弊社が展開しているPHRアプリのバックエンドにいくつかのサーバーがあり、APIを通じてクライアント/サーバー間のデータのやり取りを行っています。
今回はそのAPIの設計について触れようと思います。
REST API
REST APIについてはQiitaに公開されている記事がわかりやすくて良いです。翻訳: WebAPI 設計のベストプラクティス
APIはインターフェースなので、仕様を公開して使ってもらうことが大事です。
APIを利用する側は、APIのドキュメントから仕様を確認して使用するに値するものなのか、判断すると思います。
そのドキュメントは様々な形で公開されていて、資料が散らばっていてどこを見たらいいのかわからない、そもそも資料が更新されていなかったりなど、不便この上ないです。
そんなときにOpen API形式での設計が威力を発揮します。
Open API
Open API 正しくは Open API Specification (OAS) と呼ばれています。
OASになるまでには色々と段階を経ていますが、ここでは割愛します。
・OpenAPI Specification
https://swagger.io/specification/
OASは、REST APIの仕様の定義書を作成するフォーマットのことです。
OAS形式の定義書はyaml、json形式で記述されます。
Open API形式のIF定義書とは
今回はサンプルを用意してみました。
下記がOAS3.0で記述されたIF定義書になります。
openapi: 3.0.0
servers:
- url: 'http://localhost:8080/'
info:
description: OpenAPIによるWebAPI設計
version: 0.1.0
title: Sample API
tags:
- name: Country
description: 国に関する操作API
- name: Capital
description: 首都に対する操作API
paths:
/country/list:
post:
tags:
- Country
summary: 世界各国の国情報を返却する。※Sampleとしてアメリカ、インド、オーストラリア、日本とする。
description: 国情報として国名、人口、主な産業を返却する
operationId: getCountryInfoList
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ResCountryInfoList'
'401':
description: Unauthorixed
/capital/list:
post:
tags:
- Capital
summary: 世界各国の首都情報を返却する。※Sampleとしてアメリカ、インド、オーストラリア、日本とする。
description: 首都情報として首都名、国名、協定世界時との時差を返却する
operationId: getCapitalInfoList
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ResCapitalInfoList'
'401':
description: Unauthorixed
components:
parameters: {}
requestBodies: {}
schemas:
ResCapitalInfoList:
type: object
description: 首都情報結果
properties:
capitalInfoList:
type: array
items:
$ref: '#/components/schemas/CapitalInfo'
example:
- capitalName: Washington
countryName: United States of America
timeDifference: '-4:00'
- capitalName: New Delhi
countryName: India
timeDifference: '+5:30'
- capitalName: Canberra
countryName: Australia
timeDifference: '+10:00'
- capitalName: Tokyo
countryName: Japan
timeDifference: '+9:00'
xml:
name: ResCapitalInfoList
CapitalInfo:
type: object
description: 首都情報
properties:
capitalName:
type: string
description: 首都名
example: Tokyo
countryName:
type: string
description: 国名
example: Japan
timeDifference:
type: string
description: 協定世界時との時差
example: '+9:00'
xml:
name: CapitalInfo
ResCountryInfoList:
type: object
description: 国情報結果
properties:
capitalInfoList:
type: array
items:
$ref: '#/components/schemas/CountryInfo'
example:
- countryName: United States of America
population: 約 33009 万人
majorIndustries: 工業全般
- countryName: India
population: 約 137860 万人
majorIndustries: 農業、鉱業
- countryName: Australia
population: 約 2573 万人
majorIndustries: 農業、鉱業
- countryName: Japan
population: 約 12630 万人
majorIndustries: 製造業
xml:
name: ResCountryInfoList
CountryInfo:
type: object
description: 国情報
properties:
countryName:
type: string
description: 国名
example: Japan
population:
type: string
description: 人口数
example: '約 126,300,000 人'
majorIndustries:
type: string
description: 主要産業
example: 製造業
xml:
name: CountryInfo
このIF定義書には下記が記載されています。
・openapi
Open API 形式の宣言
・servers
接続先のサーバーURL
・info
IF定義書の情報(定義書のタイトルなど)
・tags
各APIを区分けするタグ情報
・paths
APIのパス、および仕様
・components
APIで使用されるEntityや型情報
これだけではIF定義書として読みにくいですね。
そこでSwagger Editorに登場してもらいます。
※サンプルで用意したIF定義書はGithubに公開しています。
以降は下記を使用していただいても良いです。
https://github.com/psp-engineer/SampleAPI
Swagger Editor
まずはこちらにアクセスください。
https://editor.swagger.io/
Swagger Editorが起動したと思うので、そこに先程のIF定義書を読み込ませてください。
※左ペインにペーストするか、Githubに公開しているSampleAPI.yamlを読み込ませてみてください。
こんな感じに右ペインにAPIの内容が出てきたと思います。
サンプルとして、国情報を取得するAPI (/country/list)、首都情報を取得するAPI (/capital/list) が表示されていると思います。
こちらは国情報を取得するAPI (/country/list) の詳細を表示しています。
上からAPIの説明/詳細、API呼び出しに必要なRequestParameter、返却値となるResponseParameterが記載されています。
ResponseParameterには返却値の例も記載されています。
これもIF定義書の中に記述されていて、サーバー起動したときにスタブデータとして実際に返却可能です。
では、実際にサーバー機能を起動してみましょう。
サーバー機能の出力と接続テスト
Swagger EditorはIF定義書の内容を基に、サーバー/クライアントのIFモジュールを自動生成してくれます。
Swagger EditorのGenerate Serverからモジュールを出力してみてください。
出力可能な選択肢がいっぱいあって困っちゃいますね!
今回はお手軽にサーバー起動したいので、nodejs-serverを出力します。
nodejs-server-server-generated.zipというファイルがDLできるので、それをお好きな場所に展開してください。
展開するとサーバー機能の基となるIFモジュールが入っています。
今回はNode.jsで出力したので、READEME.mdの通りに起動してみます。
Node.jsでサーバー機能をローカルで起動してみました。
では、次にSwagger Editorから国情報を取得するAPI (/country/list)を呼び出すコマンドを出力してみましょう。
Swagger EditorのParametersに「Try it out」のボタンがあると思います。
そこからExecuteボタンをクリックすると、Curlのコマンドが発行されます。
これをTerminalから実行してAPIにアクセスしてみましょう。
IF定義通りのResponseが返ってきましたね。
クライアント機能の出力
先程はサーバー機能の出力を行い、スタブデータの返却をしてみました。
同様にSwagger Editorからはクライアント機能も出力可能です。
この機能が非常に強力で、サーバー/クライアント機能が同一のIF定義書から出力されるので、IF部分に間違いが起こりません。
外部接続の実装は非常に面倒でテストも難しいですが、OASで記述されたIF定義書があればIF部分での不要なバグを減らすことが期待できます。
今回は割愛しますが、皆さんもSampleAPIを使ってクライアントモジュールからの接続を試してみてください。
おわりに
駆け足でOpen APIについてご紹介しました。
Open APIを使うことで、以下のメリットがあります。
・APIドキュメント/IF定義書の自動生成
・サーバー/クライアント機能の自動生成
・Swagger Editorの強力な開発機能によるコーディング/テスト
弊社のような自社サービスの開発はもちろん、広く世間に公開するAPIを開発する場合においても、サーバー/クライアントの開発を異なるエンジニアがする場面では役に立つフォーマット/ツールだと思います。
皆さんもぜひ使ってみてください。