Zenn
📚

WebA API The Good Partsを読む1️⃣

に公開

はじめに

Web API The Good Partsという書籍を読みながら自分の考え整理も兼ねて記事にしようと思う。
全部が全部まとめるというわけではなく自分的に大事だなと思う点だけ。

第一章 WebAPIとは何か?

WebAPIとは

HTTPプロトコルを利用し、特定のURIにアクセスすることで、サーバー側のリソースの情報を取得したり、書き換えたりすることができるインターフェースを外部に提供する仕組み。利用者はAPIの中身(作り)を意識することなく、機能だけわかっていれば利用することができる。
ApplicationProgrammingInterfaceの略。

WebAPIを美しい設計のAPIとは

本書では美しいWebAPIを設計する方法について考えていく。ではどんなWebAPIが美しいといえるのか?美しい設計のWebAPIは以下の4点が主に挙げられる。

  • 設計の美しいWebAPIは使いやすい
  • 設計の美しいWebAPIは変更しやすい
  • 設計の美しいWebAPIは頑強である
  • 設計の美しいWebAPIは恥ずかしくない

設計の美しいWebAPIは使いやすい

WebAPIを公開するということは、自分以外の人がAPIを利用する可能性がある。WebAPIが使いにくいとそれを利用する開発者は大きなストレスを受ける。ユーザーが使いやすいWebAPIは美しい設計といえる。

設計の美しいWebAPIは変更しやすい

ウェブサービスやシステムは常に進化していくので、公開した当時と同じ内容のままで済むことは少ない。APIは自分以外の人が利用している可能性があり、そんなAPIの仕様を突然変えてしまうと、作られたサービスが突然動かなくなってしまう可能性がある。
そういった点を考慮してあらかじめ変更しやすいように設計されたWebAPIは美しいといえる。

設計の美しいWebAPIは頑強である

公開しているWebAPIは誰でもアクセスできるのでセキュリティを意識する必要がある。セキュリティを意識できているWebAPIは美しいといえる。

設計の美しいWebAPIは恥ずかしくない

WebAPIは主に開発者が目にするもの。開発者は他の開発者をコードやインターフェースといった成果物で判断する。美しくないWebAPIを公開してしまうと、そのサービスの開発者の技術レベルが疑われ、いいエンジニアが集まらない。そうなるといいサービスが作れないことになりかねない。他の開発者が集まってくるようなWebAPIは美しいといえる。

WebAPIを美しくするには

美しいWebAPIを設計するために必要な原則は以下の2点。

  • 仕様が決まっているものに関しては仕様に従う
  • 仕様が存在してないものに関してはデファクトスタンダードに従う

インターネットで利用されている様々な仕様は、誰かが勝手に決めたものではなく、大勢の人によってレビューされ、様々な視点からの検討を得て決まっている。様々な取捨選択が行われてスタンダードとなった仕様にはそれなりの意味がある。したがってそんな仕様に従うのは理にかなっている。

また、既にあるルールに従ってAPIを設計することで、他のAPIを利用したことがある開発者が利用方法を推測しやすくなったり、既存のクライアントライブラリの流用が可能になったりすることで、開発の手間やストレスを軽減することができる。
そして今ある仕様が何故そんな仕様になったのか?を理解することで、より美しいAPIを設計できるようになる。

第二章 エンドポイントの設計とリクエストの形式

エンドポイントの基本的な設計

WebAPIにおけるエンドポイントとは、APIにアクセスするためのURIのことを指す。

https://api.example.com/v1/users/me

良いURIの設計の重要な原則は、覚えやすく、どんな機能を持つURIなのかひと目でわかること。
具体的には以下のようなポイントを満たしているURIが良い設計とされている。

  • 短く入力しやすいURI
  • 人間が読んで理解できるURI
  • 大文字小文字が混在していないURI
  • 改造しやすいURI
  • サーバ側のアーキテクチャが反映されていないURI
  • ルールが統一されたURI

短く入力しやすいURI

短くて入力しやすいということは、シンプルで覚えやすい。短くてシンプルであるほうが理解しやすく、入力間違いも少ないはず。

http://api.example.com/service/api/search
よりも
http://api.example.com/search
のほうがシンプルで覚えやすい。

人間が読んで理解できるURI

理解しやすいURIにしておくことで、URIからAPIの意図が理解できて、APIのドキュメントを毎回参照する必要がなくなる。また、利用者が間違ったURIにアクセスしてしまうといったトラブルを軽減してくれる。

理解しやすいURIにするには、よく使われている英単語を利用すること。よく使われているということは、単語から機能を予測することができる。短いURIを意識するばかりに省略形をつかってしまうとかえって分かりづらいURIになってしまうので注意。

大文字小文字が混在していないURI

大文字小文字が混在しているURIはわかりづらく、間違えやすい。標準的に選択されているのは小文字。
ホスト名(api.example.com)の部分は大文字小文字は無視される仕様だが、通常は小文字で表記されるため、それに続くパス部分も小文字に統一するのがわかりやすいという考えからくるもの。

改造しやすい(Hackableな)URI

HackableなURIとはURIを修正して別のURIにするのが容易であることを意味する。
あるURIから他のURIを想像することが可能であれば、あまりドキュメントを見なくても開発を進めることができる。

http://api.example.com/v1/items/123456
というURIからはアイテムのIDが123456ということが直感的に予想ができ、つまりこの番号部分を変えると別のアイテムの情報にもアクセスできるということも予測ができる。

サーバ側のアーキテクチャが反映されていないURI

どんなサーバーソフトウェアを利用しているか、どんな言語を使って実装を行っているか、サーバーサイドのディレクトリやシステム構成がどうなっているかといったアーキテクチャ的な情報はAPIの利用者には影響がない。そいうった不要な情報はURIに反映するべきではない。
アーキテクチャがURIから予測できてしまうことにより、サーバの脆弱性を狙って悪事を働こうとする人を生んでしまう可能性もある。

ルールが統一されたURI

ルールとは利用する単語、URIの構造などを意味する。例えば以下のようなAPIはどうだろう。

  • 友達情報の取得 http://api.example.com/friends?id=100
  • メッセージの投稿 http://api.example.com/friend/100/message

友達の情報を取得するAPIにはfriendsと複数形が使われていて、IDはクエリパラメータで指定する形式になっているが、メッセージの投稿をするAPIではfriendは単数形でIDはURIのパスにいれる形式なっている。これでは統一感がないというだけでなく、クライアント側を実装する際に間違えてしまうといったトラブルを生みやすい。ルールを統一すると以下のようになる。

  • 友達情報の取得 http://api.example.com/friends/100
  • メッセージの投稿 http://api.example.com/friends/100/message

このようにURIの構造が統一されている方が開発者にとって使いやすい。

HTTPメソッドとエンドポイント

HTTPのメソッドは"何をするか"を表すもので、URIは"操作する対象
=リソース"を表すもの。1つのURIのエンドポイントに異なるメソッドでアクセスすることで、情報を取得したり、更新したり、削除したりと様々な操作を行うことができる。

メソッド名 説明 エンドポイントの例
GET リソースの取得 ユーザー一覧取得http://api.example.com/v1/users
POST リソースの新規登録 ユーザーの新規登録http://api.example.com/v1/users
PUT リソースの更新 特定ユーザーの情報更新http://api.example.com/v1/users/:id
PATCH リソースの一部変更 特定ユーザーの情報更新http://api.example.com/v1/users/:id
DELETE リソースの削除 特定ユーザーの削除http://api.example.com/v1/users/:id

データベースのテーブル名とレコードどちらにアクセスするのかを、エンドポイントで表現する。そのテーブルやレコードに対してどんな処理を行うかをHTTPのメソッドで表現する。これがWebAPI設計の基本となる。

エンドポイント設計時の注意点

エンドポイントの設計を行う際には以下の4点を注意すると良い設計ができる。

  • 複数形の名詞を利用する
  • 利用する単語に気をつける
  • スペースやエンコードを必要とする文字を使わない
  • 単語をつなげる必要がある場合はハイフンを利用する

複数形の名詞を利用する

HTTPのメソッドは動詞を示すものであり、それと組み合わせて使われるURIはリソースを表現するためのものであるため、そのリソースの表現には名詞を利用する。またリソースで表現されるものはデータベースのテーブルである場合が多く、このデータベースのテーブル名は複数形であることが多い。そのため、エンドポイントで利用する名詞にも複数形を採用するほうが自然となる。

https://api.example.com/v1/user/12345
より
https://api.example.com/v1/users/12345
のほうがよい。なぜならユーザーを保持するデータベースはusersといったように複数形で表現されていることが多いため。

利用する単語に気をつける

searchfindのような似たような意味を持つ単語で、どちらを採用するのがより適切か迷った際は、他の類似のAPIではどんな表現を使っているかを調べるのがよい。

スペースやエンコードを必要とする文字を使わない

URIで直接表現できない文字をエンポイントに含めてしまうと、文字自体が%エンコーディングされ、どのようなものなのかがひと目でわからなくなってしまうため、使わないようにする。

単語をつなげる必要がある場合はハイフンを利用する

エンドポイント内で単語を2つ以上つなげる必要が出てきた際には、単語動詞をハイフンでつなげるスパイナルケースが良い。他にもスネークケースやキャメルケースを使うこともできるが、URI中のホスト名はハイフンは許可されているがアンダースコアは使えず、大文字小文字の区別がなく、ドットは特別な意味を持つため、ホスト名と同じルールでURI全体を統一しようとするとハイフンでつなぐのが最も適しているとされる。

検索とクエリパラメータの設計

ユーザー一覧からデータを取得するといったエンドポイントがあった際、一度に数万ユーザーを取得していてはデータサイズが大きすぎてパフォーマンスに問題がある。これを解決するために、一度に取得可能な人数の上限を決めたうえで、ページングを行ってデータを取得できるようにするためにクエリパラメータを用いるのが一般的である。

ページネーションを実現するためには、パラメータで取得位置取得数を指定する。
一般的な組み合わせは、per_pageとpagelimitとoffsetの2つ。
この2つは微妙に意味が異なり、pageper_page単位で1ページ、2ページと数えるが、offsetの場合はアイテム単位で数える。
例えば、1ページ50アイテム存在していた場合に3ページ目(101アイテム目)からデータを取得する際はぞれぞれ以下のように表現する。

  • per_page=50&page=3
  • limit=50&offset=100

この際、pageは1から(1-based)、offsetは0から(0-based)で数え始めるのが一般的。

クエリパラメータとパスパラメータの使い分け

パラメータをクエリパラメータとするかパスパラメータとするかを決める際は以下の判断基準に従うとよい。

  • 一意なリソースを表すのに必要な情報かどうか
  • 省略可能かどうか

URIはリソースを表すものであるという思想から、ユーザーIDなどのパラメータは指定することで参照する情報が一意に決まるためパスパラメータとするのが適切。アクセストークンなどのパラメータは、リソースとは無関係であるし、offsetなどのパラメータは省略してもデフォルト値などで代用できるためクエリパラメータとするのが適切。

ログインとOAuth2.0

OAuthは広く第三者に公開されるAPIにおいて認可(authorization)を行うために用いられる仕組み。
ユーザー登録機能を持つサービスAがAPIを公開しており、サービスBがそれを利用した機能を提供していたとする。この時、Bのサービスに対して、Aのサービスのユーザー情報を提供してもよいかの、許可を与える仕組みがOAuthである。
OAuthでのアクセスに成功すると、BはAからアクセストークンを受け取り、このアクセストークンをAに対してのリクエストに付与することで、Aはどこまでの情報をBに与えてよいか?といった判断を行いつつ情報をBへ提供することとなる。

まとめ

  • WebAPIとは、HTTPプロトコルを活用してデータの取得・更新を行うための仕組み
  • WebAPIを設計する際はわかりやすいエンドポイントを意識する
    • 覚えやすい命名
    • 予想しやすい命名
    • ひと目で機能がわかる命名
  • ページネーションに使うクエリはper_page&page, limit&offsetのどちらかがいい

3章目以降は読んだらまた次の記事を書きます。

Discussion

ログインするとコメントできます