個人的にAPIサーバーを書くことが多く、APIクライアントの担当エンジニアと作業をする上で、効率よく作業できるAPIドキュメントの書き方を探していました。
今のところAPI Blueprintというフォーマットがしっくり来ていて、実際に私達が運用しているやり方と合わせて紹介したいと思います。
やりたいこと
当初APIのドキュメントに困っていたこと、やりたかったことは以下の通りです。
- 場所と時間に制約されず、API設計を非同期でレビューしたい
- バージョン管理したい
- 簡潔に書きたい
- リッチテキストは嫌だ!
API Blueprintとは
ざっくりいうと、MarkdownでAPIドキュメントを書くためのフォーマットのことです。
また、オープンソースの周辺ツールが非常に強力で、API Blueprintで書かれているドキュメントを読み込んでAPIのモックサーバーを建てるものや、テストケースを作成するもの、専用のHTMLRendererなどがあります。
JSON Schemaで出力できるRendererもあるようです。
出力例
実際のドキュメントは以下のように書きます。
(本当はもっといろんな書き方があるのですが、ここでは独断と偏見で可読性高そうなフォーマットを選択しています。)
# Group User
ユーザー
## ユーザー [/user]
### 個人データ取得 [GET]
+ Response 200 (application/json)
+ Body
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
### ユーザー設定変更 [PATCH]
+ Attributes
+ name: `` (string, optional) - ユーザー名
+ avater_id: `` (string, optional) - アバターID
+ Request example ユーザー名変更 (application/json)
+ Body
```js
{
"name": "つよい"
}
```
+ Request example アバターID変更 (application/json)
+ Body
```js
{
"avater_id": 2
}
```
+ Response 200 (application/json)
+ Body
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
Renderer
Rendererに掛けるとこんな感じのドキュメントが出来上がります。
ここでは、Rendererにaglioを利用しています。
API Blueprintを使ったレビューの仕方
仕様変更があったり、考慮漏れがあったりするため、APIの設計は開発中に頻繁に変わります。
サーバーとAPIクライアント間で認識の齟齬があるとビルドが壊れてしまうので、そういったことがないように私たちはAPIの設計レビューをお互いの視点から行っています。
差分が見やすかったりCIと連携するのが簡単だったりするので、レビュー用のツールとしてGithubを利用しています。
レビューは、私たちは普段以下のような手順で行っています。
- リポジトリにAPI Blueprintのコミット作ってpush
- GithubにPullRequestを作成する
- サーバー、APIクライアントの両方で認識があっているか両者がレビューする
- レビューOKならマージして、CIでRendererにかけて共有できる場所にアップロード
書き方
API Blueprintの仕様書をもとに、簡単な書き方のまとめを書いてみました。
Metadata セクション
API BlueprintはMetadataセクションから始まります。
FORMAT: X-1A
HOST: https://awesome-gameserver.com
Metadataセクションには、API Blueprint自体のバージョンや、各ツール固有の情報を書くセクションです。
よくわからなければ上のようなフォーマットで問題ないです。
フォーマットは、コロン:
で区切ったKey-Value形式です。
API Name & Description
上から読んで一番初めの見出し(Markdown上は#
)がAPI全体に関する名前と説明を書くセクションです。
FORMAT: X-1A
HOST: https://awesome-gameserver.com
# Awesome Game API
Oi! This is no time for standin' around
Resource Group セクション
API Blueprintの最上位の見出しになります。
複数のAPIをまとめるグループだと考えてもらうと伝わりやすいと思います。
# Group PlayerData
Resource group of "PlayerData" !
フォーマットは、# Group <Identifier>
となります。
2行目以降はdescriptionです。
Resource セクション
ROAにおけるResourceを定義するセクションです。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
フォーマットは、## <Identifier> [<URL template>]
です。他のフォーマットもあります。
URL templateについてはRFC 6570のものです。
Resourceセクションには、配下に必ず1つ以上のActionセクションを含む必要(SHOULD)があります。
また、以下のものを含んでもよい(MAY)とされています。
- URI Parameterセクション
- Attributesセクション
- Modelセクション
Action セクション
各リソースに対してのアクションを設定するセクションです。
Railsのcontrollerをイメージするとわかりやすいでしょうか。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
### Get User information [GET]
+ Response 200 (application/json)
+ Body
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
フォーマットは、### <identifier> [<HTTP request method>]
です。他のフォーマットもあります。
HTTP request methodにはGET
やPOST
等、HTTPメソッドを指定します。ここでは、GETを指定しています。
Action セクションには以下のルールがあります。
- 配下に必ず1つのResponse セクションを含む必要(SHOULD)があります。また、Response セクションは複数含んでもよい(MAY)です。
- URI Parameter セクションを1つ以上含んでも良い(MAY)です。
- Attributes セクションを1つ以上含んでもよい(MAY)ですが、その場合、Request セクションを指定する必要(SHOULD)があります。
URI Parameter セクション
URIパラメータを箇条書きで定義することができるセクションです。
# Group PlayerData
Resource group of "PlayerData" !
## Character Collection [/characters{?limit}]
Resources of "Character" !
### Get my characters [GET]
+ Parameters
+ limit: `50` (number, optional) - Limit if you need.
+ Default: `100`
+ Response 200 (application/json)
...
フォーマットは以下のとおりです。
+ <parameter name>: `<example value>` (<type> | enum[<type>], required | optional) - <description>
<additional description>
+ Default: `<default value>`
+ Members
+ `<enumeration value 1>`
+ `<enumeration value 2>`
...
+ `<enumeration value N>`
- parameter name にはURIパラメータ名を指定します。
- requiredとoptionalを省略した場合は、requiredが指定されます。
- typeがenumの場合、Membersに取りうる値を列挙することが出来ます。
Attributes セクション
リクエストやレスポンスに利用するパラメータを予め指定しておくためのセクションです。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
### Modify user information [PUT]
+ Attributes
+ name (string) - The name of user
+ avater_id (number) - The id of user's avater
+ Request (application/json)
+ Request (application/yaml)
+ Response 200
フォーマットはMSONになります。
Attributes セクションに記載した内容を、Request セクションやResponse セクションに継承させることが出来ます。
Model セクション
任意のタイミングで呼び出すことができるデータ型を定義するためのセクションです。
Request セクションやResponse セクションで利用することが出来ます。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
+ Model (application/json)
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
### Get User information [GET]
+ Response 200 (application/json)
[User][]
定義フォーマットは、 + Model <Media Type>
の後に実際のデータを記述します。
呼び出しフォーマットは、[Resourceの<Identifier>][]
です
Request セクション
リクエスト方法に関する定義をするためのセクションです。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
### Modify user information [PUT]
+ Request modify user's name of current session (application/json)
+ Body
```json
{
"user": {
"name": "the40san"
}
}
```
+ Request modify user's avater of current session (application/json)
+ Body
```json
{
"user": {
"avater_id": 1
}
}
```
+ Response 200 (application/json)
+ Body
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
フォーマットは、Request <identifier> (<Media Type>)
です。
Response セクション
APIレスポンスに関する定義をするためのセクションです。
# Group PlayerData
Resource group of "PlayerData" !
## User [/user]
Resource of "User" !
### Modify user information [PUT]
+ Request modify user's name of current session (application/json)
+ Headers
X-UnityVersion: X.X.X
+ Body
```json
{
"user": {
"name": "the40san"
}
}
```
+ Response 200 (application/json)
+ Headers
X-UnityVersion: X.X.X
+ Body
```json
{
"user": {
"id": 123456789,
"name": "the40san",
"avater_id": 1,
"rank": 123,
"exp": 12345678
}
}
```
+ Response 400 (application/json)
+ Body
```json
{
"error": {
"message": "There is an error."
}
}
```
フォーマットは、Response <HTTP status code> (<Media Type>)
です。
まとめ
- API Blueprintの利用例と仕様に関してのまとめでした。
- Railsとの連携がもっと強くなると嬉しいな!