オライリーのWeb API The Good Partsまとめてみた④~HTTPの仕様を最大限利用する~

## ステータスコードを正しく扱う
| ステータスコード|名前|説明
| ---- | ---- | ---- |
|200 | OK   | リクエスト成功 |
|201|Created|リクエストが成功し、新しいリソースが作られた|
|202|Accepted|リクエストが成功した|
|204|No Content|コンテンツなし|
|300|Multiple Choices|複数のリソースが存在する|
|301|Moved Permanently|リソースは恒久的に移動した|
|302|Found|リクエストしたリソースは一時的に移動している|
|303|See Other|他を参照|
|304|Not Modified|前回から更新されていない|
|307| Tempolary Redirect| リクエストしたリソースは一時的に移動している|
|400|Bad Request|リクエストが正しくない|
|401|Unauthorized|認証が必要|
|403|Forbidden|アクセスが禁止されている|
|404|Not Found|指定したリソースが見つからない|
|405|Method Not Allowed|指定されたメソッドは使うことができない|
|406|Not Acceptable|Accept関連のヘッダに受理できない|
|408|Request Timeout|リクエストが時間以内に完了しなかった|
|409|Conflict|リソースが矛盾した|
|410|Gone|指定したリソースは消滅した|
|413|Request Entity Too Large|リクエストボディが大きすぎる|
|414|Request-URI Too Long|リクエストされたURIが長すぎる|
|415|Unsupported Media Type|サポートしていないメディアタイプが指定された|
|429|Too Many Requests|リクエスト回数が多すぎる|
|500|Internal Server Error|サーバー側でエラーが発生した|
|503|Service Unavailable|サーバーが一時的に停止している|
- クライアントが意図した動作をサーバー側が完了できた場合は200系
- クライアントのリクエストが不正な場合は400系
- サーバーサイドで何か問題があったら500系
- というように、エラー内容が何かを適切に返却する
## キャッシュとHTTPの仕様
- キャッシュのメリット
    - サーバへの通信を減らすことができるため、ユーザーの体感速度をあげることができる
    - ネットワーク接続が切れた状態でのある程度サービスを継続できる
    - サーバーへの通信回数、転送量を減らすことでユーザーの通信コストを下げることができる
    - サーバーへのアクセス回数が減ることで、サーバーの維持費用を抑えることができる
- キャッシュについて考える際は中継するプロキシサーバーについても意識する必要がある
    - プロキシサーバーとはクライアントとサーバーの間に位置してやりとりを仲介する機能をはたす物のこと
    - サービス提供側がAPIへのアクセスを高速化するために配置されることがある(リバースプロキシ)
    - やりとりする際にレスポンスデータを通信量を減らすためにキャッシュする場合があり、キャッシュの情報をきちんと送っていないと意図しないキャッシュが行われてしまい、正しいデータがクライアントに届かなくなってしまう可能性がある。
- キャッシュのコントロールを適切にオリジンサーバーで行うことで、効率を高めることができる
## Expiration Model(期限切れモデル)
- 予めレスポンスデータに保存期間を決めておき、期限が切れたら再度アクセスをして取得を行う。
## Validation Model(検証モデル)
- 今保持しているキャッシュが最新であるかどうかを問合せ、データが更新されていた場合にのみ取得を行う。
## Cache-Controlヘッダ
- Cache-Controlヘッダにディレクティブを指定することで、クライアントがどのようにキャッシュすればいいかを明示することができる

|ディレクティブ名|意味|
|----|----|
|public|キャッシュはプロキシに置いてユーザーが異なっても共有することができる|
|private|キャッシュはユーザーごとに異なる必要がある|
|no-cache|キャッシュしたデータは検証モデルによって確認が必要|
|no-store|キャッシュしてはならない|
|no-transform|プロキシサーバーはコンテンツのメディアタイプやその他内容を変更してはならない|
|must-revalidate|いかなる場合もオリジナルのサーバーんへの再検証が必要|
|proxy-rebalidate|プロキシサーバーはオリジナルのサーバーへの再検証が必要|
|max-age|データが新鮮である期間を示す|
|s-maxage|max-ageと同様だが中継するサーバでのみ使用される|
## メディアタイプの指定
- HTTPのリクエスト、リクエストでは送信するデータ本体の形式を表すためにメディアタイプを指定する必要がある。
```
例
Content-Type: application/json
```
- クライアントはContent-Typeの値でデータ形式を判断する
### 代表的なメディアタイプ
|メディアタイプ|データ形式|
|----|----|
|text/plain|プレーンテキスト
|text/html|HTML文書|
|application/xml|XML文書|
|text/css|CSS文書|
|application/javascript|Javascript|
|application/json|Json|

## Xで始まるメディアタイプ
- application/x-msgpackのようにサブタイプが"x-"で始まる物がある
- IANA(Internet Assigned Number Authority)に登録されていない物をさす
- データ形式が新しく登録されたもの出会ったり、一般的ではない場合IANAに登録されていない場合があり、x-で始まるサブタイプが使われ、それが一般的に用いられることがある。
```
 application/x-yaml
```

## メディアタイプとセキュリティ
- メディアタイプが正しく設定されていないAPIはセキュリティの課題がある。
- jsonをtext/htmlで配信した場合、不正に実行されるリスクがある
## リクエストデータとメディアタイプ
- リクエスト時にもメディアタイプは利用される
    - content-type
        - リクエストボディがどんなデータ形式で送られているのかを示す
    - accept
        - クライアントが「どんなメディアタイプを受入可能か」をサーバに伝えるためにつかわれる
## 同一生成元ポリシーとクロスオリジンリソース共有
- 同一オリジンポリシー
    - とあるオリジンから読み込まれた文書やスクリプトについて、そのリソースから他のオリジンのリソースにアクセスできないように制限するもの。ウェブのセキュリティにおける重要な仕組みであり、悪意ある行動を起こしかねないリソースの分離を目的としている
- クロスオリジンリソース共有(CORS)
    - 追加の HTTPヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み
## CORSの基本的なやりとり
1. クライアントからOriginというリクエストヘッダを送る必要がある。ヘッダにはアクセス元となる生成元を指定する
```
例
http://www.example.com/
から
http://api.example/com/
へのアクセスの場合は
http://www.example.com/を指定する
```
2. サーバ側では予めアクセスを許可する生成元の一覧を保持しておいて、Originヘッダで送られてきた生成もとがその一覧に含まれているかをチェックする。もしその一覧に含まれていない場合はアクセスを許可せず403をかえす。許可されている場合はAccess-Control-Allow-OriginというレスポンスヘッダにOriginリクエストヘッダと同じ生成元を入れて返すことで、アクセスが許可されたことを示す。
## プリフライトリクエスト
- 実際に生成元をまたいだリクエストを行う前にそのリキウエストが受け入れられるかどうかを事前にチェックすること
## CORSとユーザー認証情報
- CORSではユーザー認証情報を送信する場合に追加のHTTPレスポンスヘッダを発行する必要がある
- CookieヘッダやAuthenticationヘッダを使ってユーザー認証情報をクライアントが送ってきた場合、サーバは以下のようにAccessーControl-Allow-Credentialsヘッダにtrueをセットすることで、「認証情報を認識している」ということをクライアントに返信する必要がある
```
AccessーControl-Allow-Credentials: True
```
- これがない場合ブラウザは受け取ったレスポンスを拒否してしまう

## 独自のHTTPヘッダを定義する
- HTTPはデータを包むエンベロープの役割をはたす
- HTTPヘッダはその中でメタ情報をデータにつけるために利用することができる
- 既存のヘッダでは送れないようなメタデータを送りたい場合は、独自のHTTPヘッダを定義することができる
```
例
X-AppName-PixelRatio: 2.0
```
- HTTPヘッダを新しく定義する場合は'X-'という接頭辞を最初につけて、次にサービスやアプリケーション、組織などの名前をつけるというのが一般的


## まとめ
- HTTPの仕様を最大限利用し、独自仕様の利用を最低限に止める
- 適切なステータスコードを用いる
- 適切な、なるべく一般的なメディアタイプを返す
- クライアントが適切なキャッシュを行えるように情報を返す