Web APIについて調べてみた -4章編-

##背景
1章で、APIの仕様や挙動を決定する原則の1つとして、既存の標準仕様を順守すること。とあった。（確か）
この章ではHTTPの仕様をしっかり理解しよう〜ってテーマだったので、理解しようと思う。

###読んだ本
O'Reillyの本を読んでみた
[WEB API The Good Parts](https://honto.jp/netstore/pd-book_26352551.html)

###章立て
前回のはこちら
[Web APIについて調べてみた -3章編-](https://qiita.com/danbo_lobo/items/f6e1a5947277d37d492d)
今回は4章についてまとめてみた。
メモ程度の記述なので備忘録になれば。

##HTTPの仕様を利用する意義
結論から言うと、HTTPを利用することでエンベロープは不要となる。
それだけでHTTPを利用する意義があると言える。
ではHTTPはどのような構造になっているのかというと、以下のような図となる。

![HTTP構造.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430110/913c0dee-8c65-abff-293b-99eefa2318fc.png)
特徴をまとめると、
>・一対のリクエストとレスポンスで構成されており、それぞれにはヘッダ（リクエストヘッダとレスポンスヘッダ）とボディ（リクエストボディとレスポンスボディ）がある。
・ボディはレスポンスならサーバから返ってくるデータ、リクエストの場合はサーバに送信するデータが入る。
・ヘッダはそれぞれに関するメタ情報を入れることが出来る。

となる。

###ステータスコードの扱い方
HTTPを利用していく中で、必ず注意しなければならない点が**ステータスコード**である。
この部分は3章に述べた部分のまとめと重複するので割愛する。

##キャッシュとHTTPの仕様
キャッシュの話になってきた。
ここで言うキャッシュとは、**サーバへのアクセス頻度や通信量を減らす為にクライアント側で一度取った情報を保存しておき、再度必要になった時にあらかじめ取得してあった情報を利用すること**を指す。
キャッシュのメリットを以下引用する。
>・サーバへの通信を減らすことができるため、ユーザーの体感速度を上げることができる
・ネットワーク接続が切れた状態でもある程度サービスを継続できる
・サーバへの通信回数、転送量を減らすことでユーザーの通信コストを下げることができる
・サーバへのアクセス回数が減ることで、サーバの維持費用を抑えることができる

###HTTPのキャッシュモデル
HTTPにはキャッシュの仕組みが組み込まれていて、それは２種類存在する。
①Expiration Model(期限切れモデル)
②Validation Model(検証モデル)
それぞれ順に説明する。

####Expiration Model(期限切れモデル)
期限切れモデルとは、予めレスポンスデータに保存期限を決めておき、期限が切れたら再度アクセスして取得を行うというモデルのことを指す。
いつ期限が切れるかをサーバからのレスポンスに含めて返すことが実現できる。

####Validation Model(検証モデル)
検証モデルとは、今持っているキャッシュが有効かどうかをサーバに問い合わせるモデルのことを指す。
もし今持っているキャッシュが有効だった場合、最小の情報のみ転送する形となるので
大きなデータのやり取りをするようなAPIであればある程、キャッシュの効果が高まる側面がある。（必要な分だけやりとりすればいい）
ただし、検証モデルを使用する場合には**条件つきリクエスト**に対応する必要がある。

#####条件付きリクエストとは..
条件付きリクエストは、「もし今保持している情報が更新されていたら情報をください」というもの。
クライアントが過去に取得したある時点でのデータに関する情報を送り、更新されていた時のみデータを返し、更新されていなかったら`304`のステータスコードを返しクライアントに教える流れとなる。

####クライアント側のデータ保持期限の定義
#####Heuristic Expiration(発見的期限切れ)
2つのモデルとは別に、クライアント側がどのくらいデータを保持すればよいのか決めるための方針がHTTPでは定義されている。
その定義の中に**発見的期限切れ**というものが定義されている。
この発見的期限切れとは、クライアントがキャッシュの期限を自分で決めることを指す。
例えば最終更新が1年前だったとしたら、しばらくキャッシュしても大丈夫かどうか考えたり、アクセス結果1日１回しか更新されていないならキャッシュを保持しようだとか**クライアント側**が独自の判断でアクセス回数を減らすようにする。
よって、クライアント側の管理が不可欠である。

####キャッシュさせたくない！時の対処法
APIの性格上、キャッシュを全くさせたくない場合もある。
こうした時はHTTPのヘッダを使って明示的に「キャッシュしてほしくない」と伝えるのが良い。
ブラウザ側でキャッシュをさせない方法などググれば色々出てくるのでみるとよい。
[ブラウザでキャッシュをさせない方法いろいろ](https://www.kotalog.net/archives/3516)は例として挙げる。

####Varyヘッダ
######Varyって何？
ここで少しHTTP構造をおさらい。構造はライン・ヘッダ・ボディに分かれていました。
この**ヘッダ**の部分でVaryという種類があり、一般的にVaryヘッダと呼ばれている部分を指す。（以下Varyヘッダと表記）
Varyヘッダは「どのヘッダによってコンテンツが変わったか」を示すレスポンスヘッダで、「キャッシュに対してキャッシュキーの追加を指示する」意味合いも持っている。
公式では[Vary](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Vary)と記載があるので参照すると良いかもしれない。

#####Varyヘッダの出来ること
- サーバ駆動型コンテントネゴシエーションを利用する場合にVaryヘッダを付けることでデータを取得できる

- 複数のヘッダ名をコンマ区切りで指定できる

####Cache-Controlヘッダ
Cache-Controlヘッダとは、複数のディレクティブを指定できるヘッダのことを指す。
指定できるディレクティブの一覧は以下の通り。

|ディレクティブ名|意味|
|---|---|
|public|キャッシュはプロキシにおいてユーザーが異なっても共有することが出来る|
|private|キャッシュはユーザーごとに異なる必要がある|
|no-cache|キャッシュしたデータは検証モデルによって確認が必要|
|no-store|キャッシュしてはならない|
|no-transform|プロキシサーバはコンテンツのメディアタイプやその他内容を変更してはならない|
|must-revalidate|いかなる場合もオリジナルのサーバへの再検証が必要|

##メディアタイプを指定する
メディアタイプとは、データの形式のことでレスポンスデータがどんなデータなのかを示す為に利用される。
そもそもの仕様として、HTTPのリクエストおよびレスポンスでは、送信するデータ本体の形式を表す為にメディアタイプを指定する必要があるのだ。
もっと具体的に言えば、レスポンスデータとしてJSONにするか、XMLにするか、画像にするか〜などを指定する。

###レスポンス時のメディアタイプ指定方法
レスポンスでは**Content-Type**というヘッダを利用してメディアタイプを指定する。
一方で、このヘッダを利用すると、クライアント側ではデータを読み込めないケースも出てくるリスクも伴う。
Content-Typeの書き方例は以下の通り。

```bash:メディアタイプの書き方
# ----- 構文 ----- #
Content-Type: トップレベルタイプ名/サブタイプ名 ;パラメータ
# ----- 例 ----- #
Content-Type: application/json
Content-Type: image/png
```

著書内では、代表的なメディアタイプの一覧が記載されていた。詳細は本を読んで欲しい。

####他にもいろいろ。メディアタイプ
メディアタイプの中には`x-`で始まるものもあるらしい。
この表記は、そのメディアタイプがIANAに登録されていないことを示している。
（IANAとは、インターネットに関連する番号を管理する組織で、他にもドメイン管理やIPアドレスの割り当てなどインターネットにおける非常に重要な役割を担っている。メディアタイプもIANAが管理している。）
例として、`x-`で始まるメディアタイプが挙げられていた。

|メディアタイプ|データ形式|
|---|---|
|application/x-msgpack|MessagePack|
|application/x-yaml|YAML|
|application/x-plist|プロパティリスト|

####自分でメディアタイプを定義するには？
自分で定義する時に`x-`を使えばいいのかというと、そうではない。
`x-`の表記による方法は廃止された為だ。
では、どうするのかというと、サブタイプについていくつか定義してあるものを利用する。
もっと具体的に言うと、先頭に付ける文字で区別している。
以下では、`vnd.`を先頭に付けることで区別している例である。

```
# ----- 例 ----- #
Content-Type: application/vnd.ms-excel
```

`vnd.`以外にどんなサブタイプがあるのかというと、以下のような表になる。

|ツリー名|接頭辞|
|---|---|
|Standard tree(標準ツリー)|なし|
|Vender tree|vnd.|
|Personal(Vanity) tree|prs.|
|Unregistered tree|x.|

####JSONやXMLを用いた新しいデータ形式を定義したい場合
こうした時は、データ形式に`+`を追記して形式を表記すると、データ形式を定義することが出来る。

```
# ----- 例 ----- #
Content-Type: application/rss+xml
## 上記ではRSSフィードを用いると定義している
Content-Type: application/atom+xml
## 上記ではAtomフィードを用いると定義している
```

###リクエスト時のメディアタイプ指定方法
方法は以下2つがある。
>・Content-typeヘッダを利用する
・Acceptヘッダを利用する

Content-typeはレスポンスヘッダと同様に、どんなデータ形式で送られてくるのかを示す際に使われる。
Acceptヘッダは、複数のメディアタイプを列挙することが出来る。特徴としてはWebPと呼ばれるGoogleが普及を目指している新しい画像フォーマットが優先されるように指定が入っていることが挙げられる。
WebPについての説明は[WebPとは？フォーマットの違いや作成方法](https://digitalidentity.co.jp/blog/creative/webp.html)を参考にすると良い。

##まとめ
・HTTPの仕様を最大限利用し、独自使用の利用を最小限に抑えると良い
・適切なステータスコードを利用しましょう
・なるべく一般的なメディアタイプを使いましょう

##感想
HTTPのキャッシュモデルは２種類あって、用途に応じて利用すると良さそう
リクエストヘッダ、レスポンスヘッダ、共にさまざまなメディアタイプ指定があるが適切に行うこととする
次回は設計変更について書かれていたので、変更する場合の対処法を学習していこうと思う