今さらだけど「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)」を読みました。
せっかくなので自分なりにまとめてみます。

# 1. URLについて 

- 短く入力しやすいURL  
　   ×：http\://sample.com/search-api/service/api/search  
　   ○：http\://sample.com/api/search  

<!-- dummy -->
- 人間が読んで理解できるURL  
   　×：http\://sample.com/api/u  
   　○：http\://sample.com/api/user  
　   略すのもだめ　products -> prod  

<!-- dummy -->
-  大文字小文字が混在していないURL  
　   ×：http\://sample.com/api/getUserInfo  
　   ○：http\://sample.com/api/user  
　   基本はすべて小文字  

<!-- dummy -->
-  改造しやすい（Hackable）なURL  
　   ×：http\://sample.com/api/item/a/12345  
　   ×：http\://sample.com/api/item/b/67890  
　   ○：http\://sample.com/api/item/12345  
　   ○：http\://sample.com/api/item/67890　 

<!-- dummy -->	
-  サーバ側のアーキテクチャが反映されていないURL  
   　 ×：http\://sample.com/cgi-bin/get_user.php?user=100  
  　 ○：http\://sample.com/api/user?id=100  

<!-- dummy -->
- ルールが統一されたURL  
 　  userはidを指定するのに、itemはクエリを使うなどの不統一はだめ  

# 2. HTTPメソッドについて
- GET  
    リソースの取得
- POST  
    リソースの新規登録
- PUT  
    既存リソースの更新
- DELETE  
    リソースの削除  
- PATCH  
    リソースの一部変更  
- HEAD 
    リソースのメタ情報の取得  

    ※ 基本的には、GET/POST/PUT/DELETEの４つをサポートする 
    GET,POSTしか使えない場合 
    リクエストヘッダX-HTTP-Method-Overrideを使う
		
		POST /X/XX HTTP/1.1
		Host XXX.com  
		X-HTTP-Method-Override: DELETE

# 3. ネーミング選定指針について
- 複数形の名詞を利用する  
　   複数だとわかりにくい単語は単数形にしてもよい  

<!-- dummy -->
- 極力動詞は使用しない

<!-- dummy -->
- 利用する単語に気を付ける  
   　 迷ったら[ProgrammableWeb](http://www.programmableweb.com/)というサイトなどで探す

<!-- dummy -->
- スペースやエンコーディングを必要とする文字を使わない  

<!-- dummy -->
- 単語をつなげる必要がある場合はハイフンを利用する  
  　 URIのドメイン名のルールと合っているため

# 4. エンドポイント設計について
- ひとつの画面を表示するためにコールするのが１つのAPIで済むようにする

<!-- dummy -->					
- なんらかのデータをサーバに保存する場合にも１回のコールで済むようにAPIを用意する	 

# 5. レスポンスデータの設計について
- データフォーマットはJSONをデフォルトとし、必要がある場合のみXMLに対応する  

<!-- dummy -->
- 様々なユースケースを考慮し、一度に返すデータはなるべく詳細にする  
    例）ユーザ情報を返す  
        ID、名前、写真、住所など  

<!-- dummy -->
- ただし、データが大きすぎる場合、クライアント側で選択できるようにする  
    例えば、パラメータにsmall, medium, largeをつけると取得する項目を変えるようにする

<!-- dummy -->
- 不要な階層化はせず、なるべくフラットにする

<!-- dummy -->
- もちろん階層化したほうが良い場合もある
    例えば、メッセージの送信者と受信者があり、その下にユーザデータをつける場合など	 

		sender_id:12345,
		sender_name:aaaaa,
		receiver_id:67890,
		receiver_name:bbbbb					

			↓
					
		sender: {
			id:12345,
			name:aaaaa
		},
		receiver:{
			id:67890,
			name:bbbbb
		}					
	
<!-- dummy -->
- JSONのトップレベルを配列にしない  
    JSONインジェクションという脆弱性に対するリスクが大きくなる  
    ※ JSONインジェクション  
    → ScriptタグでJSONを読み込む手法。トップレベルが配列だと、JavaScript構文エラーにならずに、データが取得できてしまう。					

<!-- dummy -->
- 日付のフォーマット  
    RFC3339を推奨  
    → インターネット上で用いる標準形式として決められたもののため  
    例）2015-10-12T11:30:22+09:00	

<!-- dummy -->
- 巨大な数字は文字列にして返す  
    18桁などの整数は、JavaScriptが64bit浮動小数として扱うため誤差がでる  

<!-- dummy -->
- エラーの表現  
    - 適切なステータスコードを返すこと  
        エラーメッセージを返していてもステータスコードが200だとクライアント側に負担をかけることになる
    - エラーの際にHTMLが返らないようにする  
    - メンテナンスなどでサービスを止める場合  
        - ステータスコードは503を返す  
        - HTTPヘッダのRetry-Afterを使って、メンテナンスが終わる時刻を返す  

# 6. HTTPの仕様について
- ステータスコード
    - 100番台  
        情報
    - 200番台  
        成功
    - 300番台  
        リダイレクト  
    - 400番台  
        クライアントサイドに起因するエラー
    - 500番台  
        サーバサイドに起因するエラー  

<!-- dummy -->
- データ更新時のベストプラクティス  
    - PUTやPATCHは200（OK）とともに操作したデータを返却
    - DELETEは204（No Contents）を返す					

<!-- dummy -->
- クライアントエラーについて
    - 401（Unauthorized）は認証エラー
    - 403（Forbidden）は認可エラー  
    認証とは、「アクセスしてきたのが誰であるのかを識別すること」				
    認可とは、「特定のユーザに対してある操作の権限を許可すること」  
    → つまり、401は「あなたが誰だかわからないよ」、403は「あなたが誰だかはわかったけど、この操作はあなたには許可されていないよ」	

<!-- dummy -->
- サーバエラーについて  
    500（Internal Server Error）はログをきちんと監視して、管理者に通知が行くように設定しておくこと

<!-- dummy -->
- クロスドメイン問題について  
    CORSの利用

<!-- dummy -->
- 独自HTTPヘッダの定義について  
    - 「X-」という接頭辞をつける  
    - その後はサービス・アプリ名や組織名、そしてハイフンを挟んでIDを付ける	 
    例）X-abc-original-id				

# 7. バージョンについて
- APIのバージョン  
    URIにバージョン情報を含める方法が最もよく利用されている  
    例）http\://api.abc.co.jp/v2/users/

<!-- dummy -->
- モバイルアプリのアップデートについて  
    アプリ起動時に、現在のバージョンとサーバ側で配信するサポートバージョンを比較し、利用者にアップデートを案内する仕組みを仕込んでおく

# 8. セキュリティについて
- セッションハイジャック対策
    - HTTPSにする

<!-- dummy -->
- XSS（クロスサイトスクリプティング）対策  
    - 以下のレスポンスヘッダを使用する（JSONインジェクション対策にも有効）

			X-Content-Type-Options: nosniff		

    - JSON文字列のエスケープを行う（SCRIPTタグを無効にする）

<!-- dummy -->
- XSRF（クロスサイトリクエストフォージェリ）対策  
    - サーバのデータ更新を行うようなアクセスに関しては、GETメソッドを利用せずPOST, PUT, DELETEを用いること  
    - 正規のフォームにワンタイムトークン（少なくともセッションごとにユニークなトークン）を埋め込んでおき、そのトークンのないアクセスは拒否する

<!-- dummy -->
- JSONインジェクション対策
    - メディアタイプをクライアントに返す

			Content-Type: application/json

    - JSONデータのトップレベルを配列にしない。必ずオブジェクトにする

# 9. 大量アクセス対策
- ユーザごとにアクセス制限する
    - 何を使ってユーザを識別するか
    - リミット値をいくつにするか
    - どういう単位でリミット値を設定するか
    - リミットのリセットをどういうタイミングで行うか  
        - たとえば１分間に６０回をアクセスの上限とした場合、１分間の間に６１回アクセスがあった場合はエラーを返し、また１分が経過したらアクセスができるようになる、といった具合  
        - 一般的には１時間が多い

<!-- dummy -->
- 制限値を超えた場合の対応
    - 429 Too Many Requests を返すべき
    - エラーの詳細をレスポンスに含めるべき
    - Retry-Afterヘッダを使って次のリクエストまでの待ち時間を指定してもよい

<!-- dummy -->
- レスポンスにレートリミットを含める場合  
    以下はヘッダに格納する場合のデファクトスタンダード
    - X-RateLimit-Limit  
        単位時間あたりのアクセス上限
    - X-RateLimit-Remaining  
        アクセスできる残り回数
    - X-RateLimit-Reset  
        アクセス数がリセットされるタイミング