銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

【技術書まとめ18】Web API The Good Parts

毎週1冊技術書を読んでブログでアウトプットすることが目標で今回が第18弾です。

今回は Web API The Good Parts を読みました。

Web APIの設計、開発、運用について解説しており、Web APIの開発者は必読と言われている本です。

今後のAPI開発で活かせそうなところ満載の良書でした。

Web API: The Good Parts

Web API: The Good Parts

 

f:id:ysk_pro:20181230095506p:plain

1章 Web APIとは何か

  • Web APIとは、あるURIにアクセスすることで、サーバ側の情報を書き換えたり、サーバ側に置かれた情報を取得したりすることができるwebシステムで、プログラムからアクセスしてそのデータを機械的に利用するためのものである。機械的にと言うのは、ブラウザを使って人間が直接アクセスすることを目的としたURIではないことを意味している
  • 新しいシステム、サービスを公開する力を持った開発者にAPIを公開することで、彼らがサービスに付加価値を与えてくれ、コアとなる自分たちのサービスがより発展する可能性がある
  • サービスにある機能を追加したいと思った時、デファクトとなっているサービスがすでに存在し、APIを公開している場合にはそこに繋いだ方が有利であることが多い。APIを用意することで様々なサービスと共存共栄することができるようになる
  • スマートフォンのアプリケーションがサーバと通信する必要がある場合、Web APIが利用されるのが最も一般的である
  • 設計の美しいWeb APIは変更しやすいモバイルアプリケーションの場合、アプリケーションのアップデートのタイミングはユーザー次第であり、バージョンアップをしたとしても古いバージョンを使うユーザーは存在し続けてしまうAPIの仕様を急に変化させるとそうした古いバージョンのアプリケーションは動かなくなってしまうので、APIの変更をいかに利用者に影響なく行うかは重要である
 

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

  • Web APIにおけるエンドポイントとはAPIにアクセスするためのURIのことであり、一般的なwebページのURIの設計の考え方がそのまま適用できる
  • 良いURI設計の原則は、覚えやすく、どんな機能を持つURIなのかが一目でわかることである
  • URIに大文字は使わず、すべて小文字を使うべき。HTTPにおいてURIは、スキーマとホスト名を除いて大文字と小文字は区別されるため、大文字を使うと別のURIとなってしまう
  • HTTPメソッドのPUTとPOSTの使い分け:どちらもサーバ側の情報を変更するためのメソッドであるが、Web APIではデータを修正する場合にPUTを用い、新しいリソースを生成する場合はPOSTを用いるのが一般的である
  • データの集合と個々のデータをエンドポイントとして表現し、それに対する操作をHTTPメソッドで表す考え方は、Web API設計の基本であり、多くのAPIがこれに沿った設計となっている
  • エンドポイントには複数形の名詞を用いるのが基本である。また、エンドポイント内で単語を2つ以上繋げる必要がある場合はハイフンを利用することが多い
  • クエリパラメータとパスの使い分け:一意なリソースを表すのに必要な情報はパスに入れた方が良く、省略可能な情報はクエリパラメータに入れる方が良い
  • ホスト名とエンドポイントの共通部分は「api.example.com」が主流であり、わかりやすさ、簡素さの観点から適切であると言える
  • 「1スクリーン1API、1セーブ1APIコール」という言葉があり、何度もAPIへのアクセスを繰り返すことは、速度の問題だけでなく、データの一部だけが表示されてしまう状態や、保存の際に一部のデータだけが保存されて整合性が保たれなくなってしまうといった問題を引き起こす可能性もあるので極力避けるべきである
  • 良い設計を見極めるには様々なAPIの実際の設計を調べ、比較してみることも重要である
 

3章 レスポンスデータの設計

  • JSONXMLよりも広まった理由は、JSONの方がシンプルで同じデータを表すのにサイズが小さくて済むこと、webの世界においてクライアントのデフォルト言語であるJavaScriptとの相性がとても良いことがあげられる
  • JSONPを使うと、JSONをscript要素を使ってJavaScriptとして読み込み、ドメインを超えたアクセスが可能となる。JSONPに対応しているAPIは多く存在するが、必要がないのであればセキュリティの観点からはなるべく対応しない方がよいとされている
  • クエリパラメータを使って、レスポンスの内容をユーザーが選択できるようにすることも有用である
  • レスポンスデータをフラットにするか階層化させるかについてGoogleJSON Style Guideでは「なるべくフラットにした方がいいが、階層構造を持った方がわかりやすい場合もある」とされており、それに従うのが良い
  • レスポンスで配列を返したい場合に、配列をそのまま返すことも、オブジェクトに包むこともできるが、セキュリティの観点からオブジェクトに包んだ方がベターである。トップレベルが配列であるJSONは、JSONインジェクションという脆弱性に対するリスクが大きくなる
  • 各データ項目(JSONのキー)の名前のつけ方のポイント
    • 多くのAPIで同じ意味に利用されている一般的な単語を用いる
    • なるべく少ない単語数で表現する
    • 複数の単語を連結する場合、連結方法はAPI全体を通して統一する:JSONではキャメルケースを使うのがよいとされているが、スネークケースなどを使っているAPIも多数存在する
    • 変な省略形は極力利用しない
    • 単数形/複数形に気をつける:そのキーで返るデータが複数なのか単数なのかで使い分ける(データを配列で返すときは複数形に、それ以外は単数形にする)
  • サーバがエラーを返す際に真っ先に行うべきことは、適切なステータスコードを使うことである。エラーの詳細を返す方法は、HTTPのレスポンスヘッダに入れて返す方法と、レスポンスボディで返す方法があるが、多くのAPIはレスポンスボディにエラーメッセージを格納する方法をとっている
 

4章 HTTPの仕様を最大限利用する

  • HTTPのキャッシュの仕組みをAPIでも利用する。HTTPのキャッシュは、2つのタイプがある
    • Expiration Model(期限切れモデル):あらかじめレスポンスデータに保存期限を決めておき、期限が切れたら再度アクセスをして取得を行うもの
    • Validation Model(検証モデル):今保持しているキャッシュが最新であるかを問い合わせて、データが更新されていた場合にのみ取得を行うもの
  • Content-Typeヘッダを使ってメディアタイプを指定するのは非常に重要であり、すべてのAPIは適切なメディアタイプをクライアントに返すべきである。クライアントの多くは、Content-Typeの値を使ってデータ形式を判断しており、その指定を間違えるとクライアントが正しくデータを読み出すことができないケースが出てくるためである
  • 独自のHTTPヘッダを定義して利用することも可能である
 

5章 設計変更しやすいWeb APIを作る

  • 一度公開したWeb APIの仕様を変更する場合は、新しいAPIを別のエンドポイント、あるいは別のパラメータをつけたURIなど、何らかの新しいアクセス形式で公開するのが良い。つまり、古い形式でアクセスしてきているクライアントに対してはそれまでと変わらないデータを送り、新しい形式でのアクセスには新しい形式のデータを返すといった複数のバージョンのAPIを提供するということである
  • APIのバージョンを表す方法は、URIのパスに”/v2/“のようにバージョンを埋め込む方法が最も一般的である
  • バージョニングのルールとして広く知られている手法にセマンティックバージョニングがある。Rubyなどでも基本的な考え方が導入されている。”1.2.3”という表記でそれぞれの数値はメジャー、マイナー、パッチと呼ばれ、以下のルールが適用される。(APIURIのバスにはメジャーバージョンのみを含める場合が多い)
    • メジャーバージョン:後方互換性のない変更が行われた際に増える
    • マイナーバージョン:後方互換性のある機能変更、あるいは特定の機能が今後廃止されることが決まった場合に増える
    • パッチバージョン:ソフトウェアのAPIに変更がないバグ修正などを行ったときに増える
  • 自社のアプリ向けAPIなどの場合には、あらかじめAPIの提供が終了した際の仕組みをクライアント側にも組み込んでおくべきである。一番簡単なのは強制アップデートで、アプリケーションを立ち上げた際に、現在のバージョンと最低限サポートされるクライアントのバージョンを比較し、サポートの切れたバージョンを使っていた場合は「サービスを使い続けるにはアップデート」してくださいと表示して、AppStoreなどを開くことである
 

6章 堅牢なWeb APIを作る

  • 本来アクセスできないはずの情報はサーバ側できちんとチェックをし、アクセスを禁止しておくべきである
  • パラメータなどを修正してリクエストを送ってくる場合もあるので、クライアントから送られてきた情報を信頼せず、サーバ側でも整合性をきちんとチェックする必要がある
  • 同じリクエストを再度送信される場合もあるので、そのような場合を想定したサーバ側でのチェックが必要となる
  • 一度に大量のアクセスをされてしまう問題を解決するための最も現実的な方法は、ユーザーごとのアクセス数を制限することである。つまり単位時間あたりの最大アクセス回数(レートリミット)を決め、それ以上のアクセスがあった場合にエラーを返すようにする
  • XSSXSRFなど通常のwebと同様のセキュリティだけでなく、JSONハイジャック(APIからJSONで送られてくる情報を悪意ある第三者が盗み取ること)などAPI特有の脆弱性に気を配る必要がある
  • セキュリティ強化につながるHTTPヘッダをきちんとつけるべきである
 

おわりに

ここまで読んでいただきありがとうございます。

Web APIの開発に関わっていて本書をまだ読んでいない方は是非読んでみることをおすすめします!

Web API: The Good Parts

Web API: The Good Parts

 

やっぱり年末年始は読書が捗りますね。

来週も頑張ります!