書評：Web API: The Good Parts

[「Web API: The Good Parts」](https://www.amazon.co.jp/Web-API-Parts-%E6%B0%B4%E9%87%8E-%E8%B2%B4%E6%98%8E/dp/4873116864)の書評になります。
著者：水野 貴明
出版社：オライリージャパン
発売日：2014/11/21

# 所感
APIを触る機会が増えそうなのでマナー講習として読みました。
すぐに使えそうな知識としてエンドポイントの設計やレスポンスデータの設計マナーが身につきます。
APIを外部に公開することがメイン(一章でオススメされている)の話になっているので社内で完結するような開発では得られるものが半減するように感じました。

APIの設計から運用まで抑えておくポイントがまとまっています。
題名は難しそうなのですが、基礎的なことが中心でかなり読みやすい本でした。
APIのお作法が自分の中で確立できていない人におすすめできる本です。

#目次
[1.Web APIとは何か](#1-Web APIとは何か)
[2.エンドポイントの設計とリクエスト形式](#2-エンドポイントの設計とリクエスト形式)
[3.レスポンスデータの設計](#3-レスポンスデータの設計)
[4.HTTPの仕様を最大限利用する](#4-HTTPの仕様を最大限利用する)
[5.設計変更をしやすい Web APIを作る](#5-設計変更をしやすい Web Apiを作る)
[6.堅牢な Web APIを作る](#6-堅牢な Web APIを作る)

##1-Web APIとは何か
API(Application Programing Interface)
Application:特定の動作をする機能
Programing Interface:プログラミングでの呼び出し方

プロトコルがHTTP(S)を使うのでエンドポイントはURIになります。

著書では"APIを公開すべし!"と述べてあります。
理由は、公開したAPIを基盤に新しいサービスや経済圏ができるなど、ユーザーの増加が見込めるからです。
例）TwitterのAPIを公開することにより、Twitterを活用した分析やbotのサービスができたり...

公開した方がいいのはわかった。
でもセキュリティーや他の人が使いやすいAPIって難しいと思いますよね。
それをこの本は解決してくれます。

>
Web APIを美しく設計する



頻出語句
LSUDs(large set of unknown developers):不特定多数の開発者
SSUDs(small set of known developers):既知少数の開発者

##2-エンドポイントの設計とリクエスト形式
1でも書いたようにAPIへのアクセスはURIで行います。
つまりURIが分かりづらいと美しいAPIではないですよね。
#####1.短くて入力しやすい
URIに入っている語句、本当に必要？
#####2.人間が読んで理解できる
誰が読んでも同様の意味に解釈できる？変に略していない？
#####3.大文字小文字が混在していない
ホストが小文字しか許容してないのでそっちに合わせよう
#####4.改造しやすい
一つのURIを見て他のURIが想像できればGood!
#####5.サーバ側のアーキテクチャが反映されていない
ユーザーはサーバがどう動いているか知りたくない。
セキュリティー的にもアーキテクチャがわからないように！
#####6.ルールが統一されている
特に単数形と複数形のルールを揃えないと一気に分かりづらくなる。
#####7.名詞にする
HTTPメソッドが動詞だから
#####8.基本複数形
エンドポイントでアクセスするリソースは集合だから
#####9.スペースやエンコードを必要とする文字を入れない
エンコードすると理解できなくなる 
#####10.単語をつなげる必要がある場合はハイフンを利用する
アンダーバーは下線に被る


#####注）パスに入れるかクエリを使うか迷った時
URIは一意なリソースを表すのに必要
＝＞一意に特定するために必要ならパスに入れる
省略可能ならクエリに入れる


##3-レスポンスデータの設計
プログラムが処理しやすいレスポンスを返す！
現在はJSONが主流なのでJSONサポートしておけば問題ない。
#####1.レスポンスをユーザーが選べるようにする
データを毎回全部返すのは多すぎる場合があります。
クエリで指定してユーザーが望むものだけ返してあげる
#####2.迷ったらフラットな構造で返す
階層構造をもつ必要があるかよく考える。
↓メリットが少ない例

```json
{
  "id": 111,
  "name": "hoge",
  "address": {
    "postal": "123-4567",
    "prefecture": "hokkaido"
  }
}
```
#####3.オブジェクトで返す
JSONには二通りの書き方があります。
配列はJSとしても正しい構文なのでメディアタイプを間違えると実行される恐れがある。
セキュリティーと可読性の観点からオブジェクトで返す。

```json
1. オブジェクト
{
  "friends": [
     {
        "id": 1,
        "name": "hoge"
     },
     {
         "id": 2,
         "name": "huga"
     }
  ]
}

2. 配列
[
  {
    "id": 1,
    "name": "hoge"
  },
  {
    "id": 2, 
    "name": "huga"
  }
]
```

#####4.エンベロープで包まない
エンベロープ：APIのレスポンスデータ構造を同じようにするための構造↓
HTTPがエンベロープの役割を果たしているので必要ありません。

```json
{
  "header": {
    "status": "success",
    "errorCode": 0,
  },
  "response": {
     // データ
  }
```

#####4.日付フォーマット
RFC3339が一番分かりやすい。
例）2021-08-14T11:30:22+09:00
#####5性別データ
sex:生物学的な性別（その他、男、女）
gender:社会的な性別（Agender, Transなども含む）
主流はgenderを文字列で持たせる。

##4-HTTPの仕様を最大限利用する
HTTPはエンベロープの役割を果たしています。
HTTPの仕様を守ることで使いやすいAPIができます。

####よく使うステータスコード
- 200 Ok
get, patch, putでよく使う

- 201 Created 
postの時に使う

- 204 No Content
deleteの時によく使う
削除したデータは必要ないため

- 301 Moved Permanently
恒久的なリダイレクト

- 302 Found
一時的なリダイレクト

- 307 Temporary Redirect, 308 Permanent Redirect
307は302に、308は301に似ているがredirectの際にgetを許容しないところで違う。
=>postでアクセスしたエンドポイントのリダイレクトにもpostでアクセスする。

- 304 Not Modified
キャッシュ

- 401 Unauthorized
認証エラー
*認証：ユーザー不明

- 403 Forbidden
認可エラー
*認可:権限

- 405 Method Not Allowed
URIはあっているがメソッドが違う

- 406 Not Acceptable
指定されたデータ型式で返せない

- 415 Unsupported Media Type
指定されたデータを受け取れない（サーバーが）

- 409 Conflict
id登録の際に既に存在する時など

- 429 Too Many Requests
リクエストが多すぎる

- 503 Service Unavailable
サーバーが一時的に機能していない=>メンテナンス時

####キャッシュの利用
1. 期限切れモデル
cache-control（相対時間）とexpires（絶対時間）
二つとも指定されている場合。cache-controlが優先される

2. 検証モデル
Last-Modifiedで検証する場合
リクエストヘッダにIf-Modified-Sinceを加える
Etagで検証する場合
If-None-Matchを加える

#####キャッシュさせたくない時
Cache-Controlに以下指定
基本的にno-cache（検証モデルを用いる）
精密情報はno-store（プロキシサーバーに保存しない）

#####レスポンスヘッダvary
キャッシュのキーを増やすイメージ
User-Agentでスマホ用やpc用のレスポンスを管理している場合など表示が変わる時は指定する必要がある!
例）vary: User-Agent,Accept-Language

#####プロキシが持つキャッシュ
public:同じプロキシにおいて共有可能
private:ユーザーごとに異なる必要がある

#####適切なメディアタイプを指定
x-で始まるメディアタイプはIANAで管理されていないもの
*text/javascriptではなくapplication/javascriptが実は正しい。



#####CORS（クロスオリジンリソース共有）
オリジンが違うくてもアクセスを許可する設定
方法：プリフライリクエストで許可をもらう
その際リクエストヘッダにオリジンを追加
*オリジン：スキーム、ホスト、ポート番号から判断

##5-設計変更をしやすい Web Apiを作る
APIを運用していく中で昨日を追加したり構造を変更する可能性は大いにあります。
その際、変更しやすいAPIを作る必要がある。

#####バージョンをURIに入れる
クエリやメディアタイプに入れるよりわかりやすい。
入れるのはメジャーバージョンだけで良い

#####後方互換性を持つ
互換性がないとユーザーの負担が大きい。

#####API公開のポイント
1. テスト用のAPI(サンドボックス)を作ってあげる
2. APIコンソールを用いブラウザで実行できるようにしてあげる
3. クライアントの見本コードを書いてあげる


##6-堅牢な Web APIを作る
ユーザーが安心して使えるAPIを目指す。

- XSSに備える
htmlに不正なjsを埋め込み実行する攻撃
=>jsをエスケープする

- XSRFに備える
ユーザーが意図しない偽装リクエストを送る攻撃
=>XSRFトークンで認可することにより防ぐのが一番楽

- JSONハイジャックに備える
レスポンスのJSONを盗み取る
=>メディアタイプの指定をする

- 認可ユーザーの攻撃を防ぐ
支払いの偽装やパラメータの改竄など
=>セキュアなHTTPヘッダをつける
    - X-XSS-Protection <br>
        XSSの検出

    - x-contenttype-options: no-shiff<br> 
       IEのメディアタイプ無視機能停止

- DoS攻撃(大量アクセス)に備える
レートリミットを設定する
    - リミット:単位時間あたりのアクセス上限
    - リメイン:アクセスできる残り回数