概要
Web API設計についてまとめた本です。
https://www.oreilly.co.jp/books/9784873116860/
2014年発行なので少々年数は経っていますが、API設計の考え方を学ぶ上では古くなっていないと思います。
1章 Web APIとは何か
定義
- HTTPプロトコルを利用してネットワーク越しに呼び出すAPI
- プロトコルとしてHTTPを使うため、エンドポイントはURIによって指定する。
- 簡単に言えば、URIにアクセスすることで、サーバ側の情報を書き換えたり、サーバ側に置かれた情報を取得できるwebシステムで、プログラムからアクセスしてどのデータを機械的に利用するためのもの。
- 「機械的に」というのは、人間がブラウザ越しに直接アクセスすることを目的としていないというのが要点。HTMLのように人がブラウザ上で読むための情報ではなく、JSONなどの形式でシステムが二次利用するための目的で利用する。
歴史
- 2003年のAmazonのProduct Advertising APIが先駆け。
- 現代ではスマホアプリもSNSやソーシャルゲームなどの各種WebサービスもWeb APIを公開するのが一般的となっており、APIエコノミーと呼ばれる潮流が加速している。
効果
- APIを公開することは外部にデータを公開するということなのでリスクを伴うが、別のサービスとの繋ぎこみを他者がやってくれたりしてサービス成長に繋がる可能性もある。
- Sam Ramjiによれば、20世紀に現実世界のビジネスが直接販売から間接販売に移行したのと同様、Webの世界も個々のサービスが自らのサイトで直接サービスを行う"直接販売"から、APIを提供し、それを複数組み合わせたアプリケーションがユーザーにサービスを行う"間接販売"モデルになったと言う。
設計
- 何をAPIとして公開するかを決め、アクセス先となるエンドポイントを決め、やり取りの方法や適切なレスポンスデータの形式を考え、セキュリティやアクセス制限について考えていく必要がある。
- 使いやすいWeb APIの設計は必ずしもRESTの設計思想に合致する訳ではないので、RESTにこだわりすぎない。
2章 エンドポイントの設計とリクエストの形式
URI
- Web APIにおけるエンドポイントとは、APIにアクセスするためのURIのことを意味する。
- 覚えやすく、どんな機能を持つURIなのかが一目でわかることが重要。
- 短く入力しやすいURI
- 不要な情報や意味の重複を避ける。
- 人間が読んで理解できるURI
- 略語や英語以外の単語を使わない。
- 大文字小文字が混在していないURI
- 改造しやすい(Hackableな)URI
- 仕様やドキュメントをなるべく見なくても開発出来るようにする。
- サーバ側のアーキテクチャが反映されていないURI
- サーバソフトウェアや利用されている言語などの情報は利用者には不要。
- ルールが統一されたURI
- ユーザのデータを取得するAPIの場合、IDをURIのパスに含めるか、クエリパラメータで指定するかというのは設計段階で選択することになるが、機能ごとにこのルールが違うと利用者が使いづらいのでルールを統一する。
- 短く入力しやすいURI
- URIとHTTPメソッドの関係は、操作するもの(URI)と操作方法(メソッド)の関係になる。基本として、情報を取得する場合はGET、修正する場合はPOST。
エンドポイント
- 自分のサービスにおける機能を一覧にして、どの機能をWeb APIとして公開するか検討する。
- ユーザIDのような「あるデータの集合」と「個々のデータ」をエンドポイントとして表現し、それに対してHTTPのメソッドで操作を表していく考え方がWeb API設計の基本であり、多くのAPIがこれにそった設計となっている。
- サーバのリソースアクセス用のエンドポイント設計の注意点
- 複数形の名詞を利用する。
- 利用する単語に気をつける。
- スペースやエンコードを必要とする文字を使わない。
- 単語をつなげる必要がある場合はハイフンを利用する。
- エンドポイントから取得したデータから対象を検索・絞り込みするためにクエリパラメータを利用する。大量のデータはページネーションを使って取得数と取得位置を決めて順番に検索する。
- クエリパラメータとパスの使い分けとして以下のような判断基準がある。
- 一意なリソースを表すのに必要な情報かどうか
- 省略可能かどうか
- パラメータを指定しなければデフォルトで利用されるので、デフォルトが主体であればクエリパラメータにする。
ログインとOAuth
- ログイン周りは外部サービスのAPIとしてOAuthの利用をまず検討すべき。
- 自分のサービスのユーザ情報を利用するようなAPIを公開する場合はGrant Typeとして何の情報に対してアクセスさせるかを決める。
APIデザイン
- 自分のサービスのホーム画面で表示される情報について、「ユーザ情報」や「おすすめ商品」などの個々の情報にアクセスするAPIではなく、ひとつに詰め込んだ"ホーム画面表示用"APIを開発するなど、ユーザにとっての利便性を高さを意識する。
- REST LEVEL3 APIでは、レスポンスデータにある操作のあとに行う行動のためのリンクを提供し、クライアントがあらかじめエンドポイントを知らなくても動作可能にする。
3章 レスポンスデータの設計
データ形式
- Web APIとは、HTMLの代わりにプログラムで処理をしやすいデータ形式を返すWebページの一種と言える。
- 現状、データ形式として選択すべきはシンプルで分かりやすいJSON一択。
- データ形式はHTTPのAcceptというリクエストヘッダで指定することも出来るが、分かりやすいのでURIでクエリパラメータ指定するのがおすすめ。
レスポンスデータの渡し方
- JSONをサーバからブラウザに返す方法としてJSONPがある。関数の引数としてJSONを指定し、ブラウザ側でcallback関数を呼び出されて必要なデータを渡すというもの。
- callback関数はクエリパラメータで指定できるようにしておくのが一般的。
<script src="https://api.example.com/v1/users?callback=cbfunc>
- JSONPはサーバがエラーを返した時に、クライアント側で何が起きたが分からず正しく対応できないという問題点がある。なので、メタ情報をレスポンスボディに格納する必要がある。
データ構造
- 1つの作業を完結するために複数回のアクセスを必要とするようなAPIは「Chatty(おしゃべり)」と表現される。ネットワークトラフィックを増幅させてクライアント側にも処理の手間を増やすので、なるべく必要と想定されるデータを一度に渡せるAPIを心がける。
- レスポンスの内容をユーザが選べるようにすれば効率的。
- エンベロープは基本不要。なぜなら、HTTP自体がエンベロープの役割を果たしているので冗長となるから。
- データはなるべくフラットに表現する方が良いけど、階層構造の方が分かりやすい場合もあるので場合による。
- データを配列のまま渡すかオブジェクトで包んで渡すかという選択肢に関しては好みの問題とも言えるが、JSONインジェクションという脆弱性に対応するためにオブジェクトで渡す方がセキュリティ上望ましい。
各データのフォーマット
- 命名に関しては誤用を防ぐためになるべく一般的で分かりやすい名前を付ける。
- 性別のデータを数値で返すか文字列で返すか、sexなのかgenderなのかはサービスの性質によって使い分ける。
- 日付データは標準形式であるRFC 3339形式を使うのが良い。
エラーの表現
- ステータスコードを定義し、適切なエラーの詳細をクライアントに返す。
- HTTPのヘッダにエラーメッセージを格納する例はほとんどないので、ボディに格納するので問題なし。
4章 HTTPの仕様を最大限利用する
- HTTPのステータスコードを理解して正しく利用する。
- HTTPのキャッシュの仕様を理解し、ネットワークトラフィックを減らしサーバの負荷軽減を図る。
- キャッシュの期限はサービスの性質によって適切な値が変わる。頻繁な更新を伴うサービスであれば期限を短くする。
メディアタイプの指定
- クライアントの多くはContent-Typeの値でデータ形式を判断するので、正しくメディアタイプを指定してクライアントに返す。
同一生成元ポリシーとクロスオリジンリソース共有
クロスオリジンリソース共有(CORS)は異なる生成元(ドメイン)からのアクセスに対して、特定の生成元からのみアクセスを許可する仕組み。JSONPよりもセキュアな仕組みであり、対応しておくべき。
5章 設計変更しやすいWeb APIを作る
- Web APIはサービスの変更に柔軟に対応できるように設計変更しやすくしておく必要がある。
- 利用者が仕様変更時に急に使えなくなったりすることを防ぐ。
APIのバージョン管理
- 基本的には一度公開したAPIは出来る限り変更しない方が良い。新しい機能は別のエンドポイントや別のパラメータをつけたURIで公開するのが望ましい。要するに、複数のバージョンのAPIを提供する。
- バージョン管理番号はセマンティックバージョニングを使うのが適切。
- URIのパスにバージョンを入れて管理するのが一般的。
APIの提供終了
- 事前に終了日時をアナウンスし、それまでの対応を呼びかける。
- ステータスコードに410(Gone)を返すように設計し、クライアント側に提供終了が分かるようにする。
6章 堅牢なWeb APIを作る
- 基本的なHTTPアクセスでのセキュリティ対応だけでなく、Web APIは機械的なアクセスが前提となるため通常のWebサイトとは別の対策が必要となる。
- 基本としてHTTPSにしておく。
- XSS対策をする。ユーザからの入力とJSONで渡すデータの内容はチェックする。
- JSON内の文字列はエスケープする.
- JSONハイジャック対策をする。
- セキュリティ強化につながるHTTPヘッダをきちんとつける。
- DDoS対策としてアクセスリミットをかける。