- 5章 設計変更をしやすいWeb APIを作る
- 一度公開したWeb APIの仕様を変更するのは、どのような場合においても問題が発生する危険性がある
- 特にLSUDs向けのAPIの変更は大変。APIの変更を利用者全員に通知することも難しく、利用者が対応を行えないまま変更してしまうと信頼を失ってしまう
- モバイルアプリケーション向けのAPIはSSKDsで変更の影響範囲は小さいが、モバイルクライアントはユーザーがアップデートしなければ古いまま。AppStoreなどでは公開に審査が必要で更新に時間がかかる、あえて古いバージョンのアプリを使い続ける人がいる、OSのバージョンが古くてアップデートできない人もいるなどが、API更新の際の問題となる
- 自分たちのサービスで使っているAPIの場合は多少楽だが、ブラウザのキャッシュの問題が残る。APIの返すデータとクライアントのコードで、キャッシュされている内容の不整合により問題が起こる可能性がある。特にiOSのWebViewではキャッシュが長時間保存されることが有名で、キャッシュ更新に気を配らなかった場合に問題を起こす。
- 一度公開したAPIをできるだけ変更しないことで問題を回避できる。つまり、新しいAPIを別のエンドポイントで表すなど、複数のバージョンでAPIを提供するのがよい
- URIには、ソフトウェアと同様にバージョン番号を振っていくのがよい。バージョン番号の表し方についてはいくつかの方法が提案されており議論もあるが、ここでは最も一般的でわかりやすいURIのパスにバージョンを埋め込む方法を中心に考える
サービス | 接頭辞 |
---|---|
https://graph.facebook.com/v2.0/me |
|
https://api.linkedin.com/v1/people |
|
Foursquare | https://api.foursquare.com/v2/venues/search |
ぐるなび | https://api.gnavi.co.jp/ver1/RestSearchAPI |
Dropbox | https://api.dropbox.com/1/account/info |
mixi | https://api.mixi-platform.com/2/people/@me/@friends |
- ソフトウェアのバージョンには1.2.3のように複数の数字をドットでつないだものが用いられ、それらの数字は先頭からメジャーバージョン、マイナーバージョン、ビルド番号orリビジョンorメンテナンス番号と呼ばれる。バージョニングのルールとして広く知られている手法にはセマンティックバージョニングがあり、これにおいてはそれぞれの数字はメジャー、マイナー、バッチと呼ばれ、以下のようなルールが適用される
どを行ったときに増える
- メジャーバージョンは後方互換性のない絵変更が行われた際に増える
- マイナーバージョンは後方互換性のある機能変更、あるいは特定の機能が今後廃止されることが決まった場合に増える
- バッチバージョンはソフトウェアのAPIに変更がないバグ修正などを行った際に増える
- すなわち、メジャー番号だけをURIに含めることは、メジャーアップデートの際にのみAPIのバージョンを上げるということを意図している。TwitterやFacebookなど巨大なAPIが1.1や2.0というマイナーバージョンをURIに含めているが、これはむしろ少数派で、URIに入れるのはメジャー番号だけにしたほうが無難
- クエリ文字列でバージョン情報を指定する方法もある。パスで指定する方法との違いは、バージョン指定を省略できるかどうかで、省略すると多くの場合最新版が利用される
- バージョンが省略可能だと、アップデート時にトラブルが起こる可能性もあるので、筆者としてはパスにバージョン情報を入れた方がよいと考える
- メディアタイプでバージョン情報を指定する方法もある。Githubのバージョン3のAPIでは、メディアタイプを
application/vnd.github.v3+json
としている。APIのバージョンというプレゼンテーションレベルの指定がURIに含まれることがなくなり、HTTPの文法に則った美しい方法と言えるが、クライアントライブラリによって独自のメディアタイプをエラーと認識してしまう可能性もある - 独自のHTTPヘッダを定義して、そこでバージョンを指定するようになっているものもある。例えばGoogleのAPIでは
Gdata-Version
というヘッダを利用することができる
- 最もよく利用されているのはパスにバージョンを入れる方法で、特にこだわりがなければこの方法をとるのが無難
- APIのバージョンを増やすことは公開側のメンテナンスのコストも、クライアント側の対応のコストも増やすことになる。後方互換性を保つことが可能な変更は、可能な限り同じバージョンでのマイナーバージョンアップで対応し、どうしてもという場合にのみバージョンを上げるべき
- AmazonのAWSなどではクエリパラメータを省略すると最新のバージョンにアクセスできる場合があるが、筆者の意見としてはこれは不要(注:5.2.3節参照)。GoogleのAPIではバージョンを指定しないと古いバージョンが利用され、どちらかというとこちらの方が理にかなっていると考えられる
- APIを終了する場合、事前に終了日時をアナウンスし、それまでに対応してくれるように周知徹底しなければならない
- Twitterでは2012年にバージョン1.1を公開し、それに伴い1.0の廃止を段階的に行った。
- まずAPI 1.1のリリースの発表は2012年8月に行われ、それから6ヵ月後に1.0が廃止になることが告げられた。1.1 リリース一か月後の2012年10月に1.0のエンドポイントが変更され、URIにバージョンが入った新しいURIでないとアクセスできなくなる
- 2013年の3月には"Blackout Test"と呼ばれる、一時的に1.0のAPIを停止するテストが行われ、その後継続的に何度か行われた
- 1.0 の廃止日時は2013年5月7日となっていたが、Blackout Testを行うため6月11日に延期され、実際にその日に廃止された
- たとえばAPIが公開終了した際には、ステータスコード410(Gone)を返し、APIの公開が終了したメッセージを返すことが考えられる。自社のスマートフォン向けAPIなどの場合、あらかじめAPIの提供が終了した際の仕組みをクライアント側に組み込んでおくべきで、例えば強制アップデートを行うなどがある。このような体験はあまり頻繁にユーザーに行わせるべきではないが、前触れなくエラーが出るよりはマシなので必ずやっておく
- APIの中には、ウェブ上で公開する利用規約にサポート期限を明記しているものがある。このように期限を明記すると逆にその期間は廃止できなくなるのであまり頻繁に行うべきではないが、サービスの形式によっては必要である
- LSUDs向けのAPIではなるべく汎用性の高い設計にすることが求められ、このようなAPIを洋服のフリーサイズになぞらえ"one-size-fits-all(OSFA)"アプローチと呼ぶ人もいる。このような汎用的なAPIは特定の開発においては使いにくく、Netflixでは、サーバー側の汎用的なAPIとクライアントとの間に"Client Adapter Code"を実行する層を挟み、様々なデバイスに対応できるようにしている。この層はオーケストレーション層とも呼ばれるもので、クライアント側で自分たちのデバイスの機能に合わせてエンドポイントを修正することができる。このように、リソース試行のAPIを用意し、その前にこうしたオーケストレーション層を置くことで、修正を容易にしたり複数の環境をサポートするのが容易になる
- [Good] APIのバージョンの更新は最低限にとどめ、後方互換性にも注意する
- [Good] APIのバージョンはメジャーバージョンをURIに含める
- [Good] APIの提供終了時はすぐに終了するのではなく、最低6ヵ月公開を続け