【本の感想】Web API the Good Partsを読んで得たこと10個

# どんな内容なのか

Web APIの設計、開発、運用についての解説書。APIは設計次第で使いづらいものになるだけではなく、公開後の保守運用も難しくなってしまいます。
そのためAPIを美しく設計することがとても重要です。本書では「設計の美しいAPIは、使いやすい、変更しやすい、頑強である、恥ずかしくない」という考えのもと、
APIをどのように設計し運用すればより効果的なのか、ありがちな罠や落とし穴を避けるにはどういう点に気をつけなければいけないのかを明らかにします。
ターゲットは、URIにアクセスするとXMLやJSONなどのデータが返ってくるシンプルなタイプ――XML over HTTP方式やJSON over HTTP方式――のAPIです。
読者は、Web API設計の考え方と手法を知ることができます。

https://www.oreilly.co.jp/books/9784873116860/

# 読み始めた背景
実務でフロントエンドの実装に慣れてきた時期に、バックエンド側の実装も本格的に任せてもらえるようになりました。しかし、バックエンドはフロントエンドと違ってUIで動きを確認することができず、また、ルールや法則がいろいろあるようで暗中模索なことばかりでした。そんな中で先輩エンジニアにおススメしてもらったのがこの本です。


# 読んで得たこと10個
読んで得たこと10個を書き出していきます。

#### 1. そもそもWebAPIとは何なのか
WebAPIの定義は曖昧ではあるけれども、簡単に言うと「HTTPプロトコルを利用してネットワーク越しに呼び出すAPI」のことで、URIにアクセスすることで、サーバ側の情報を書き換えたり、サーバ側に置かれた情報を取得できたりするウェブシステムのことです。


#### 2. RESTとWeb APIは微妙に違う
RESTは一般的には「HTTPでアクセスでき、データをXMLやJSONを返すAPI」と言う認識をされていて、WebAPIとは微妙に違うようです。
RESTはRoy FieldingというHTTPの仕様策定に関わった人の論文に初めて使われた言葉だったのですが、現在は２種類の意味で使われています。
1. FieldingのRESTアーキテクチャスタイルの原則に合わせたウェブサービスシステム。
2. RPCスタイルに合わせた簡易なXML＋HTTPインターフェイスを採用したシステム。 

この定義を見ると、ウェブベースのAPIはRESTの定義にそぐわない場面が出てくるため、厳密的にはこの二つは区別して考えるべきと考えられています。

#### 3. リソースにアクセスするためのエンドポイントの設計で気をつけること
リソースにアクセスするAPIはWeb APIを作成する中でも最も多く、繰り返し設計する必要が出てくるものです。以下はとても大事なポイントです。
1. 複数形の名刺を利用する
2. 利用する単語に気をつける
3. スペースやエンコードを必要とする文字を使わない
4. 単語を繋げる必要がある場合はハイフンを利用する

#### 4. クエリパラメータとパスパラメータの使い分け
使い分け方の判断基準は以下のようなものです。
- 一意なリソースを表すのに必要な情報かどうか
- 省略可能かどうか

1つ目の一意かどうかというのは、一意のデータを指定することで参照した情報が一意にきますからパスに入れた方が良いです。2つ目の省略可能かどうかはその名の通りで、パラメータが省略された場合にデフォルト値が利用されるケースが多いので、この場合はクエリパラメータが適しています。


#### 5. レスポンスデータを階層にする場合とフラットにする場合のメリット
実務ではレスポンスデータは階層にするように設計していたのですが、本書ではGoogleのJSON Style Guideでは「なるべくフラットにしたほうがよいけど、階層構造を持ったほうがわかりやすい場合もある」とやや曖昧な表記になっています。

しかし、例えば以下のような複数項目をまとめたいがためだけに階層構造にしてしまうのはあまりメリットがないので、

```
{
    "id": 123,
    "name": "Taro",
    "profile": {
        "birthday": 0410,
        "gender": "male",
        "languages": [ "ja", "en" ]
    }
}
```
このようにフラットにした方が見た目あまり違いがなく、JSONデータは大きくならずに済みます。
```
{
    "id": 123,
    "name": "Taro",
    "birthday": 0410,
    "gender": "male",
    "languages": [ "ja", "en" ]
}
```
データを階層化するときは不要な階層化はないかを確認するのが良さそうです。

#### 6. エラーの詳細をクライアントに返すべき
エラーが発生した場合はステータスコードを返すだけでは、エラーの内容が曖昧で利用者は何をなおして良いのかがわかりません。そこで、エラーの詳細を返すことが重要になってきます。
1つ目はHTTPのレスポンスヘッダに入れて返す方法です。

```
X-MYNAME-ERROR-CODE: 2013
X-MYNAME-ERROR-MESSAGE: Bad authentification token
X-MYNAME-ERROR-INFO: http/.....
```

2つ目はレスポンスボディで返す方法です。以下のようにJSONのレスポンスボディとしてエラーの際の専用のデータ構造を用意してそこにエラー情報を格納します。

```
 "error": {
        "code": 2013,
        "message": "bad authentication token",
        "info": "http:example.com/api/v1/authentication"
    }
```
クライアントから見た時の利便性も考えるとボディの方が処理を行いやすく、現実に公開されているAPIはほとんどがボディにエラーメッセージを格納する方法をとっているため、レスポンスボディにエラーの詳細を入れる方法で問題ないでしょう。


#### 7. ステータスコードを正しく使うべき
ステータスコードとは、HTTPのレスポンスヘッダの先頭に必ず入っている３桁の数字です。ステータスコードは先頭の数字1桁でおよその意味合いを示してます。

100番台：情報レスポンス
200番台：成功レスポンス
300番台：リダイレクト
400番台：クライアントエラー
500番台：サーバエラー

世の中にはこの原則を守っていないAPIもたくさんあります。例えばどんなアクセスでも200を返し、エラーかどうかはコンテンツの中で記述しているケースです。

```
HTTP/1.1 200 OK
Content-type: application/json

{
 "head":{
    "errorCode":1001,
    "errorMessage":"Invalid pparameter"
},
 "body":{
   :   
 }
```
これでも意味を理解することはできますが、HTTPステータスコードにはそれぞれに意味があるので適切なコードを返したほうがクライアントがエラーを正しく認識してくれる可能性が高くなります。


#### 8. バージョン番号の付け方
通常ソフトウェアのバージョンをつける際には、1.2.3や4.5.6.7.のように複数の数字をドットで繋いだものが使われます。そしてその数字はそれぞれ先頭から、メジャーバージョン、マイナーバージョンと呼ばれ、3つ目以降はビルド番号、リビジョン、メンテナンスバージョンなど様々な呼び方をされます。
バージョニングのルールとして広く知られている手法にセマンティックバージョニングがあります。”1.2.3”という3つの数字をドットで繋いだもので、それぞれ、メジャー、マイナー、パッチと呼ばれ、以下のようなルールが適用されます。
- パッチバージョンはソフトウェアのAPIに変更がないバグ修正などを行った時に増える
- マイナーバージョンは広報互換性のある機能変更、あるいは特定の機能が今後廃止されることが決まった場合に増える
- メジャーバージョンは広報互換性のない変更が行われた際に増える


#### 9. HTTPSを使っても100%安全ではない
HTTPSが正しく使われていれば、通信の盗聴やセッションハイジャックなどは不可能になりますが、HTTPSを使ってさえいれば100%安全かというとそんなことはありません。例えば、Webサーバや暗号機能を提供するライブラリにバグがある可能性も考えられます。
HTTPSを利用していてもクライアントがわできちんと処理を行っていない場合には安全性が担保できなくなるので、常にセキュリティに関する方法をキャッチアップして対応し続けていく必要があります。

#### 10.レートリミットを設けることで一部のユーザーによる過度のアクセスによる負荷を防ぐ
一度に大量のアクセスがやってきてしまう問題を解決するための最も現実的な方法は、ユーザーごとのアクセス数を制限することです。つまり、単位時間あたりの最大アクセス回数をきめ、それ以上のアクセスがあった場合にエラーを返すようにします。
こうしたレートリミットを行うにあたっては、以下のことを決める必要があります。
- 何を使ってユーザーを識別するか
- リミット値をいくつにするのか
- どういう単位でリミット値を設定するか
- リミットのリセットをどういうタイミングで行うか

# おわりに
実務でAPIを実装しながら本をみて振り返ったり、先輩から「〇〇に関しては〇〇の章に書いてあるから読んでみて」と言われて何度も読み返したりしたので、本書のおかげでAPIの基本を理解できるようになった実感があります。今後もお世話になり続ける本でした。

# 参考書籍
https://www.oreilly.co.jp/books/9784873116860/