Web API入門#8 〜HTTPヘッダー・キャッシュ〜

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ HTTPヘッダーの種類・情報・認証、キャッシュについて

■ Web API入門についての過去記事
・ [Web API入門#1 〜APIとWeb API、Webの概要〜](https://qiita.com/s79ns/items/8dd2f06145cbf9464b99)
・ [Web API入門#2 〜REST、アーキテクチャについて〜](https://qiita.com/s79ns/items/bd8b1f50c34ada016196)
・ [Web API入門#3 〜URIの基礎知識〜](https://qiita.com/s79ns/items/c4ec2db048fa3b13638e)
・ [Web API入門#4 〜クールなURIの設計方法について〜](https://qiita.com/s79ns/items/e2f3b6f66059c2917206)
・ [Web API入門#5 〜HTTPの基礎〜](https://qiita.com/s79ns/items/31a6f6affdd28bb8b026)
・ [Web API入門#6 〜CRUDとHTTPメソッド〜](https://qiita.com/s79ns/items/9b0f76f4bfdf4140a506)
・ [Web API入門#7 〜ステータスコードの意味と活用〜](https://qiita.com/s79ns/items/043a00330e1259673167)

## HTTPヘッダーのおさらい

HTTPヘッダーは、HTTPメッセージにおけるリクエストとレスポンスのメタデータ（付加情報）のことです。
HTTPヘッダーがあることで、クライアントからのリクエストをサーバーが受け取った時にどう扱うべきかや、レスポンスをクライアントが受け取った時に、クライアント側はそのレスポンスをどう処理するべきなのかを判別することができます。

## メディアタイプのHTTPヘッダー

HTTPヘッダーは色々な種類がありますが、今回はメディアタイプと呼ばれるものをご紹介します。

#### MIMEメディアタイプ

MIME（マイム）は、Multipurpose Internet Mail Extensionsの略で、多目的なインターネット上のメールの拡張という意味です。要約すると、限られたテキストでしか使用することしかできないインターネットの電子メールにおいて、様々な書式で扱えるようにする規格のことです。略してメディアタイプと呼ぶこともあります。

ヘッダーのcontent-typeにメディアタイプをtype/subtypeという形式で指定し、charsetパラメータには文字エンコーディングを指定します。

```
Content-Type: application/json; charset=utf-8
```

上の例では、utf-8でコーティングされたデータがレスポンスで返ってきます。
また、主要なTypeや意味、type/subtype例を下の表にまとめましたので、参考にご覧下さい。

| 主要なType | 意味 | type/subtype例 |
|:---------:|:---:|:--------------:|
| text | 人が読んで直接理解できる | text/plain |
| image | 画像データ | image/jpeg |
| audio | 音声データ | audio/mpeg |
| video | 動画データ | video/mp4 |
| Application | その他のデータ | application/json |

## 様々なヘッダー情報

上の内容以外にも様々なヘッダー情報がありますのでご紹介します。

| ヘッダー種別 | 例 | 意味 |
|:----------:|:--:|:---:|
| 言語タグ | Content-Language: ja-JP | リソースを表現する自然言語 |
| コンテントネゴシエーション | Accept: text/html, application/xml | クライアントが処理可能なメディアタイプ |
| ボディの長さ | Content-Length: 447 | レスポンスボディのサイズ |
| チャンク転送 | Transfer-Encording: chunked | 大きなデータを分けて転送する |

#### 言語タグ

言語タグの例では、Content-Language: ja-JPと指定すると、日本語と表現することができます。
Content-Languageを使うことにより、リソースを表現する自然言語を指定しています。

#### コンテントネゴシエーション

MIMEメディアタイプで登場した、Content-Typeと似ていますが、Content-Typeはサーバー側がレスポンス時にデータの種別を決めて返すものでした。
一方、コンテントネゴシエーションは、クライアントがリクエスト時に、このメディアタイプであれば対応できると交渉（ネゴシエーション）する時に使います。例の1行目で、Accept: text/html形式のメディアタイプであれば対応できますという意味です。

#### ボディの長さ

例のContent-Length: 447であれば、レスポンスボディのサイズが447バイトであるという意味です。

#### チャンク転送

動画データのようなサイズの大きなデータを、1度に送らずに分割して送る時の情報です。

## HTTP認証のためのヘッダー

リソースのアクセスに制限がかかっている場合は認証が必要です。
その際は、リクエスト時に認証情報というものをヘッダーに付与しリクエストを送ります。
そして、サーバーに送られてきたヘッダーの認証情報が正しければ、サーバー側はリソースをレスポンスとして返し、誤りの場合、エラーコード401 Unauthorizedが表示される可能性があります。

認証方法の種類については以下の通りです。

| 認証方法 | 仕様 | 特徴 |
|:-------:|:---:|:---:|
| Basic認証 | base64でエンコードされた<br>ユーザーIDとパスワードを使用 | 簡単にデコードできる<br>HTTPSによる通信暗号化が必須 |
| Digest認証 | デコードできないハッシュ化された<br>パスワードを使用 | メッセージは暗号化できないので<br>HTTPSによる通信暗号化が必須 |
| Bearer認証 | 権限付きのトークンを取得して使用する | OAuth2.0で保護されたリソースなどの認証に使う |

#### Basic認証

下の例ですと、Basic認証であれば、AuthorizationヘッダにBasic種別が指定されており、次にユーザー名とパスワードが文字列のように並んでいます。これはbase64というエンコードで、文字列の部分は人間には読めないですが、デコード（解読）を簡単に行うことができます。
人間には読めないようにリクエストを送っているだけで、これでは全く安全とは言えません。

```terminal
Authorization: Basic qasdfghjklp==
```

#### Digest認証

Basic認証とは異なり、デコードができないようにハッシュ化という方法で、パスワードが簡単に読み取れなくなります。しかし、メッセージ本文は暗号化されませんので、HTTPSによる通信暗号化が必要です。

#### Bearer認証

最近使われている認証方法で、リクエストしたユーザーに権限付きのトークンを取得し、そのトークンを使用してサーバー側にリクエストを送ります。リクエストを受けたサーバーは、リクエスト内容が正しければ、レスポンスを返します。

## キャッシュ

キャッシュは、取得したリソースを再利用する仕組みのことです。
毎回リソースを取得していると、通信が何度も発生してしまい効率が悪いので、ローカルにリソースを保存し、取得したリソースを再利用します。
しかし、キャッシュを利用していると、取得したリソースの情報が古くなってしまい、リソースが更新されているがキャッシュを利用していることによって、リソースの情報に差異が発生するというデメリットもあります。

現在の仕様では、Cache-Controlヘッダを使うことがほとんどで、それによりリソースの検証と再取得を行うのか条件を設定します。

| 指定方法 | 目的 |
|:-------:|:----:|
| Cache-Control: no-store | キャッシュしない |
| Cache-Control: no-cache | キャッシュするが再検証する<br>（持っているキャッシュは最新か） |
| Cache-Control: max-age=86400| 相対的な有効期限を設定<br>単位は秒（86400秒=24時間）<br>24時間後にリソースを取得する |
| Cache-Control: must-revalidate| 必ず検証する |