読者です 読者をやめる 読者になる 読者になる

Web API: The Good Partsを読んだ

書評

Web API: The Good Parts

Web API: The Good Parts

業務ではiOSアプリとバックエンドの開発を両方担当しているので、APIの設計を何回かやってきた。しかし、自分なりのやり方でやってきた部分が多かったので、最近発売されたWeb API: The Good Partsを読んでちゃんとした設計について学ぶことにした。

得られた学びをメモとして残す。

HATEOAS

HATEOAS(Hypermedia As The Engine Of Application State)という設計方法を初めて知った。HATEOASではまず、サーバー側はレスポンスに関連するエンドポイントを含め次にアクセスするAPIを簡単に辿れるようにする。クライアント側は最初のエンドポイント以外はハードコーディングせずにレスポンスに含まれるエンドポイントだけにアクセスを制限する。このようにすることで、アプリケーションのワークフローをクライアント側で制御するのではなく、サーバーサイドで制御できるようになる。

HATEOASのメリットとしては、特にモバイルアプリケーション開発の文脈で重要なこととして、最初にアクセスするものを除いてエンドポイントをハードコーディングせずに済むということだと思う。一度リリースしてしまったアプリにハードコーディングされたエンドポイントは互換性を死守しなければならないが、レスポンス中に含まれるものを使うのであれば柔軟にエンドポイントを変更することが可能になる。

例として、配列を返すレスポンスに前後のページへのリンクを含める場合はこのようになる。

{
  friends: [
    {
      id: 12345,
      name: "Alice"
    },
    {
      id: 12346,
      name: "Bob"
    }
  ],
  hasNext: true,
  links: [
    {
      uri: "http://api.example.com/v1/users?page=3&per_page=20",
      rel: "next"
    },
    {
      uri: "http://api.example.com/v1/users?page=1&per_page=20",
      rel: "prev"
    }
  }
}

エラー時のレスポンス

エラーが発生した場合は適切なHTTPステータスコードを返すのは当然としてエラーの詳細情報を返す必要がある。それらはレスポンスボディに含めることが多い。複数のエラーが同時に発生する場合を考慮して、詳細情報を配列で返す方が親切だと思う。詳細情報には、エラーメッセージだけでなく、API提供側で独自に定義した詳細コードが含まれることがある。詳細コードはステータスコードと混同しないように4桁にして、1000番台は汎用的なエラー、2000番台はユーザー情報に関連するエラーというようにカテゴリー分けすると便利。

{
  errors: [
    {
      message: "Not Found",
      code: 1013
    }
  ]
}

クライアント側の実装としては、HTTPステータスコードではなく詳細コードごとにエラーメッセージを出し分ける方がユーザーにとってフレンドリーなUIになるだろう。

キャッシュ

HTTPのキャッシュの仕様には2種類あり、期限切れモデルと検証モデルがある。

期限切れモデルでは、キャッシュの保存期限をサーバー側で指定し、クライアントはその期限中は通信を行わなくなり期限が切れたらアクセスを再開する。期限の指定方法はCache-ControlヘッダーとExpiresヘッダーの2種類ある。Cache-ControlDateヘッダーの日時からの経過時間を指定する。Expiresは期限を表す日時を指定する。Cache-Controlは頻繁には更新されないデータに使われ、Expiresは天気情報など決まった時間に更新されることがわかっている場合に使われることが多い。

検証モデルでは、クライアントは今持っているキャッシュが有効かどうかを問い合わせて無効だったときだけ取得する。サーバー側はデータを返す際Last-ModifiedヘッダーとETagヘッダーを返し、クライアントに保持してもらう。そして、クライアントが問い合わせるときに送られたIf-Modified-SinceIf-None-Matchと比較して変化しているかどうかを判定する。変化していればキャッシュは無効とみなし再取得させる。期限切れモデルとは異なり、毎回アクセスは発生しているため、データ自体がそこまで大きくないとあまり効果はない。

使い分けとしては、頻繁に更新されないものや定期的に更新されるようなデータは期限切れモデルを使い、頻繁に更新される可能性があるものは検証モデルを利用するのがよさそうだ。

その他

OAuth2.0のフロー、各HTTPステータスコードの説明、APIにまつわるセキュリティなどAPIを設計する上で必要となる周辺知識がのっている。個人的に気になっていたAPIオーケストレーションの話はそこまで取り上げられていなかった。