注目の記事

【API Blueprintの使い方】Web APIの仕様書を書く・読む・実行する

2016.05.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

【API Blueprintの使い方】Web APIの仕様書を書く・読む・実行する

できればドキュメント書きたくないなー。はやくAPI実装したい!俺の頭の中に全部仕様入ってるから!俺が仕様だ! ... その仕様、API Blueprintでドキュメントにおこしませんか?

はじめに

デバイスが多様化し、その違いを吸収する統一的なインターフェースが求められる昨今、Web APIはその回答のひとつといえます。弊社でも、モバイルアプリとWeb APIを組み合わせてサービスを構築することがあります。

Web APIが登場する開発では、モバイルアプリ(APIクライアント)メンバーと、APIサーバメンバーのコミュニケーションが不可欠です。開発を円滑に進めるために、APIの仕様書 が必要になります。お互いがAPIの仕様を想像して勝手に開発を進めたのでは、いざ結合したときに悲惨な結果になることが目に見えているからです。

とはいえ、できればドキュメントは作りたくないもの。Web APIは、ただでさえHTTPメソッドやパラメータ、ヘッダなど記載するべき情報の種類が多く、手がかかります。そこでAPI Blueprintを使って仕様書を書き、HTMLファイルを生成して、モックサーバを立ててみます。

API Blueprintの特徴

API仕様書にかぎらず、作成するドキュメントは、書きやすく、かつ読みやすく、そして実行可能なことが理想です。2000年代は、Microsoft Wordやブログの見たまま編集モードなど、書いたもの=読むものを実現できることが効率的であるという風潮だったと感じます。ただ、最近は、書いたものをコンパイルして読める形式/実行可能な形式に変換するツールが増えてきました。Markdownなんかはその際たる例でしょう。プログラミングのレイヤでも、EmmetCoffeeScriptに見るように、直接実行可能なソースコードを書くのではなく、人間にとって書きやすい、一段高級な仕様を作り上げることで生産性をあげようとする流れを感じます。API Blueprintも、大きな役割はこれらと同じです。違いを挙げると、仕様に沿った書き方をすることで、読みやすく(HTML)かつ実行可能な(node.js)形式へ変換可能という、一石二鳥な点が優れています。

API Blueprintの優れているもう一つの点は、Markdown拡張形式で記載できることです。これにより、圧倒的にdiffが取りやすく、バージョン管理システムとの相性が抜群に良いです。これ、本当に大事。

書いてみる

前置きが長くなりましたが、本記事ではAPI Blueprintで書いた仕様書を見ながらポイントを説明します。もちろん本家のドキュメントは豊富にあるのですが、いかんせん情報量が多く、とっかかりにはそれなりの読み込みが必要だと感じました。そこで、本記事で最低限必要になるであろう記述方法に絞って記載しますので、API Blueprintを使った仕様書を作成するための第一歩を踏み出すきっかけにしてください。

やること

  1. Web API仕様書を書く
  2. Web API仕様書を読めるようにする
  3. Web API仕様書を実行できるようにする

Web API仕様書を書く

まずは書く

書いてみましょう。単純なエンドポイントの仕様です。

FORMAT: 1A

# Group ユーザ

## ユーザのエンドポイント [/v1/users]

### ユーザ登録 [POST]

#### 処理概要

* ユーザ情報を新しく登録する。
* 登録に成功した場合、アクセストークンを返す。

+ Request (application/json)

    + Headers

            Accept: application/json

    + Attributes
        + email: test@example.com (string, required) - メールアドレス(format: email)
        + password: abc123 (string, required) - パスワード(pattern: ^[0-9A-Za-z]{6,16}$)

+ Response 201 (application/json)

    + Attributes
        + accessToken: f58ba22059f5a8aa8f346e0f40987adab326041fac99029c909bef2c6300821a (string, required) - アクセストークン

構成から説明します。見出しレベルごとに、

  • リソースグループ(第一見出し)
  • エンドポイント(第二見出し)
  • HTTPメソッド(第三見出し)

そして、第三見出し以降は、あるエンドポイントへの、特定操作(HTTPメソッド)の説明になっていることがわかります。説明部分はまた特殊な記法が続いてますが、まずはこの構成が大まかに把握できていればこの先戸惑うことはないでしょう。ちなみにこのファイルをHTMLに変換すると以下のような見た目になります。

api_html

HTMLへの変換は後述します。

他のエンドポイントも作ってみる

他のエンドポイントも作成して、今度はレスポンス部分を細かくみてみます。ユーザリソースに対するGETメソッドのAPIを用意しましょう。追加する分だけ記載します。

## ユーザ情報取得 [/v1/groups/{groupId}/users{?userId,mailAddress}] -- (1)

### ユーザ情報取得API [GET]

#### 処理概要  -- (2)

* 指定した会員の情報を返す。
* userIdかmailAddressいずれかは必須。どちらも指定がない場合、BadRequestを返す。
* userIdとmailAddressがどちらも指定されている場合、userIdの情報を利用し、mailAddressは利用しない。

+ Parameters  -- (3)

    + groupId: 11440002 (number, required) - ユーザが所属するグループID
    + userId: 300 (number, optional) - ユーザID
    + mailAddress: some@example.com (string, optional) - ユーザのメールアドレス

+ Response 200 (application/json)

    + Attributes
        + user (required)  -- (4)
            + name: wada (string, required) -- (5)
            + age: 18 (number, required) -- (6)
            + type: 0 (enum, required) - ユーザ種別(0:無料ユーザ, 1:有料ユーザ) -- (7)
                + 0 (number)
                + 1 (number)
            + profile (object, required) -- (8)
            + registered: `2015-06-11T08:40:51Z` (string, required)  -- (9)
            + favorites (array) -- (10)
                + `https://dev.classmethod.jp/` (string)
        + messageHistory (array) -- (11)
            + (object)
                + id: 22345 (number, required)
                + title: 今日の献立 (string, required)
  • (1)エンドポイント - 指定可能なパスパラメータおよびクエリパラメータをブレース{}で囲んで記載します。ここで書いたパラメータは、後のParameters部分でもれなく記載しなければなりません。
  • (2)説明 - 第四見出し以降は、API固有の説明として自由に記載できます。
  • (3)Parameters - +から書き始めます。次の行以降、インデントを入れてパスパラメータ、リクエストパラメータを記載していきます。parameterName:valueの形式で書きます。valueはサンプル値として扱われます。
  • (4)Object - ここからはレスポンスボディの中身です。MSONという形式で記載することで、型の情報や必須かどうかなどのメタ情報を表現することが可能です。MSONで記載すると、サンプルとして記載している値をJSONに変換したものに加え、メタデータも別枠で表記されます。この行は、コロンを記載せずに改行してインデントを入れることで、入れ子になったJSONオブジェクトを表現しています。
  • (5)String data - 文字列データです。ダブルクォーテーションは不要です。
  • (6)Number data - 数値データです。
  • (7)Enum data - 列挙データです。取りうる値をネストして記載すると、メタ情報欄にすべて載せてくれます。APIを利用する開発者からするとcase文にどれだけ分岐を入れればよいのかわかりますから、貴重な情報ですね。
  • (8)Object data - 空のオブジェクトを表現したいときは、このように書きます。
  • (9)Escape - 文字列の中にエスケープしたい文字が入っている場合は、バッククォートで囲むことで全体をエスケープさせることが可能です。
  • (10)Array - 配列データのサンプルです。
  • (11)Array Object - 配列データとしてオブジェクトが入っているサンプルです。

PUTやDELETEも、メソッドこそ違えど記載する内容は同じです。Parameters, Request, Response, そしてボディを表現するMSONを押さえておけば、記載できるかと思います。この仕様をHTMLに変換すると以下のようになります。

get-users-1

Web API仕様書を読めるようにする

仕様書が書けるようになったところで、自分のためにも、モバイルアプリ開発者のためにも、見やすい形に変換しましょう。作業ディレクトリは最終的に以下のような状態になります。

.
├── README.md
├── api.md  -- すべてのAPIをまとめたファイル。HTML変換の中間ファイルであるとともに、モックサーバ起動時にも利用します。(自動生成)
├── bin
│     └── converter.sh -- HTMLへの変換スクリプト
├── output -- 出力用ディレクトリ(自動生成)
│     └── api.html  -- 出力となるHTML(自動生成)
└── src
    ├── messages.md -- 別エンドポイントの仕様が記載されたファイル
    └── users.md -- 上で記載したファイル

aglioのインストールしてプレビューする

HTMLへの変換にはaglioを使います。早速プレビューしてみましょう。

$ npm install -g aglio

$ cd ~/path/to/workspace
$ aglio -i users.md --server
...
Server started on http://127.0.0.1:3000/

これで、Live Reloadが有効になったローカルサーバが立ち上がりました。あとはそのサーバへブラウザでアクセスしつつ、好きなmarkdownエディタで編集すればプレビュー環境のできあがりです。簡単ですね。

すべてのファイルを連結したHTMLファイルを生成する

見る側にとってはひとつのHTMLファイルに仕様が詰まっているほうが嬉しいものです。別のエンドポイントについて記載したmessages.mdファイルを作成し、先ほど作成したusers.mdと連結、変換することで全部入りのHTMLを作ります。bin/converter.shを以下のように記載してください。

#!/bin/bash

cd `dirname $0`

files=()
files+=('../src/users.md')
files+=('../src/messages.md')


echo 'FORMAT: 1A' > ../api.md || exit $?
cat ${files[@]} | sed -e '/^FORMAT: 1A/d' >> ../api.md || exit $?
mkdir -p ../output 2>/dev/null
aglio -i ../api.md -o ../output/api.html || exit $?

exit 0

実行すると、output/api.htmlができあがります。ブラウザでこのファイルを開けば、オールインワンの仕様書ができあがります。

api.html

Web API仕様書を実行できるようにする

さて、これで終わりではありません。今作ったmarkdownファイル、なんと実行可能です。api-mockをインストールして使います。

$ npm install -g api-mock

$ cd ~/path/to/workspace
$ api-mock api.md --port 3000
info:    Enabled Cross-Origin-Resource-Sharing (CORS)
info:    	Allow-Origin: *
info:    	Allow-Methods: GET, PUT, POST, PATCH, DELETE, TRACE, OPTIONS
info:    	Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, Referer, Prefer
info:    Listening on port 3000

http://localhost:3000/v1/groups/124445/users?userId=334へアクセスしてみます。

mock_response

JSONが返ってきているのがわかりますね。素晴らしい!

おわりに

API Blueprintを使ってWeb API の仕様書を書くことで、ドキュメント作成のコストを抑えつつ、実行可能なモックサーバを立てることができることを確認しました。APIを開発している間は、一時的にこちらのモックサーバをモバイルアプリ開発メンバーに使ってもらうようにすれば、API待ちで開発が止まることもありませんし、実際にリクエストを投げてJSONが返ってくるので、ローカルファイルで動作確認するよりも、二度手間になりません。人の手を介すステップが減る分だけ、全体品質の向上が期待できます。

この記事では、読者の方が仕様書を作成できるようになることを重視し、すべての作業を手元の環境で試しましたが、TravisCIなどのCIツールと組み合わせることによって、例えばGitHubのプッシュ/マージに反応してHTMLドキュメントやモックサーバを専用インスタンスへ自動で展開する、といった芸当が可能です。それを実際に説明しているのが、弊社かんあきひでの記事ですので、チーム開発で導入する場合は是非実践してみてください。

参考リンク