9章 HTTPヘッダ

<h1>HTTPヘッダ</h1>

 <h2>9.1 HTTPヘッダの重要性</h2>
ヘッダーはボディの付加追加の情報である。
極めて、補足説明するので、重要な情報である。

クライアントはヘッダの情報をみて、メッセージに対する挙動を確認します。

EX
リソースへのアクセス権を設定する認証やクライアントとサーバの通信回数塗料を減らすキャッシュなどのHTTP機能はヘッダで実現します。

**認証やキャッシュ機能**は*ヘッダとステータスコードと組み合わせて初めて実現できます。*


<h3>ヘッダにかく種類</h3>

1. <h6>日時</h6>
    1. DateやExpiresが日時を示すヘッダです。
    1. 日時を持つヘッダ

 | 利用するメッセージ     | ヘッダ              | 意味                                                                    | 
| ---------------------- | ------------------- | ----------------------------------------------------------------------- | 
| リクエストとレスポンス | Date                | メッセージを生成した日時                                                | 
| リクエスト             | if-Modified-Since   | 条件付きGETでリソースの更新日時を指定するときに利用する                 | 
|                        | if-Unmodified-SInce | 条件付きPUTや条件付きDELETEでリソースの更新日時を指定するときに利用する | 
| レスポンス             | Expires             | レスポンスをキャッシュできる制限                                        | 
|                        | Last-Modified       | リソースを最後に更新できた日時                                          | 
|                        | Retry-After         | 再度リクエストを送信できるようになる日時の目安                          | 


<h3>MIMEメディアタイプ</h3>
メッセージでやり取りするリソース表現の種類を指定するMIMEメディアタイプです。

電子メールから拝借してきた名前ではある。HTTPでは、このうちContent-Typeヘッダなどいくつかを利用する。


1. Content-Typeでは、どのようなメッセージボディの内容であるかを示す。

| タイプ      | 意味                             | 例                | 
| ----------- | -------------------------------- | ----------------- | 
| text        | 人が呼んで理解できるテキスト     | text/plain        | 
| image       | 画像データ                       | image/jpmg        | 
| audio       | 音声データ                       | audio/mpeg        | 
| video       | 映像データ                       | video/mp4         | 
| application | そのほかのデータ                 | application/pdf   | 
| multipart   | 複数のデータからなる複合データ   | multipart/related | 
| message     | 電子メールメッセージ             | message/rfc822    | 
| model       | 複数次元で構成されるモデルデータ | model/vrml        | 
| example     | 例示用                           | example/foo-bar   | 

:::
EX
```
Content-Type: application/xhtml+xml; charset=utf-8
```
この例もとに説明すると、
application部分がタイプです。xhtml/xmlはサブタイプです。タイプは勝手にふやすことはできないが、、サブタイプは増やすことが可能である。

※「x-」をつけることで、サブタイプをアレンジできる。
登録済みのサブタイプは、**IANA**で管理している。独自のメディアを発明する前に、調べる必要がある。
:::

<h6>サブタイプ例</h6>

| タイプ/サブタイプ                 | 意味                 |     | 
| --------------------------------- | -------------------- | --- | 
| text/plain                        | プレーンテキスト     |     | 
| text/csv                          | CSV形式のテキスト    |     | 
| text/css                          | CSS形式のテキスト    |     | 
| text/html                         | HTML文書             |     | 
| text/xml                          | XML文書(非推奨)      |     | 
| image/jpge                        | JPEG画像             |     | 
| image/gif                         | GIF画像              |     | 
| image/png                         | PNG画像              |     | 
| application/xml                   | XML文書              |     | 
| application/xhtml+xml             | XHTML文書            |     | 
| application/atom+xml              | Atom文書             |     | 
| application/atomsvc+xml           | Atomサービス文書     |     | 
| application/atomcat+xml           | Atomのカテゴリ文書   |     | 
| application/javascript            | JavaScript           |     | 
| application/json                  | JSON文書             |     | 
| application/msword                | Word文書             |     | 
| application/vnd.ms-excel          | Excel文書            |     | 
| application/vnd.ms-powerpoint     | PowerPoint文書       |     | 
| application/pdf                   | PDF文書              |     | 
| application/zip                   | ZIPファイル          |     | 
| application/x-shockwave-flash     | Flashオブジェクト    |     | 
| application/x-www-form-urlencoded | HTMLフォーマット形式 |     | 

文字コードについて、文字コードはcharsetを使って　、設定可能です。
また自然言語についても、
```
Content-Language: ja-JP
```
のように**Content=Language**を使えば、設定可能である。

コンテストネゴシエーション
前回まではヘッダに追記して**サーバ**が一方的に決定する手法でした。
しかし、クライアントとサーバが交渉して決めることも可能です。

<h4>Accept ---処理できるメディアタイプを決める </h4>

クライアントが自分の処理できる**メディアタイプをサーバに伝える**場合は、
**Acceptヘッダ**を使うことができる。

```
Accept: text/html, application/xhtml+xml, application/xml; q=0.9*/*; q=0.8
```
「q=」は優先順位を指しており、小数点以下３桁以内の0~1までの数値で、数値が大きい方を優先します。

クライアントがサーバが指定した文字コードに対応していない場合は
「406　Not Acceptable」を返す。

<h4>Accept-Charset ---処理できる文字エンコーディングを伝える</h4>

クライアントが自分の処理できる文字エンコーディングをサーバに伝える場合は
Accept-Charsetを使用する。

```
Accept-Charset: Shift, Shift_JIS, utf-8, q=0.7, *; q=0.7

```

<h4>Accept-Language ---処理できる言語を伝える</h4>

クライアントが自分の処理できる言語タグをサーバに伝える場合は、Accept-Languageヘッダを利用する。

```
Accept-Language: ja, en-us; q=0.7, en; q=0.3
```

<h2>9.7 Content-Lengthとチャンク転送</h2>
Content-Lengthは、ボディの長さを指定する。

メッセージがボディを持っている場合、基本的にContent-Lengthヘッダを利用して10進数のバイトで示す。

```
Content-Length: 5538
```

<h4>チャンク転送</h4>
チャンク転送は、「ボディを分割して転送する」。
しかし、動的に画像のサイズが変化するWebサービスの場合はファイルサイズが決まるまで
レスポンスを返せないので応答性能が低下してしまう。

このときに使用するのが、「Transfer-Encoding」である。

```
Transer-encoding: chunked
```
Transer-Encodingヘッダに「chunked」を設定すると、最終的にサイズがわからないボディを少しずつ転送することができる。

EX
```
POST/test HTTP1.1
Host: example.co.jp
Transer-Encoding chunked
Content-Type: text/plain, charset=utf-8
```

HTTP 1.1では、全てのHTTP1.1実装はチャンクエンコーディングを受信できなければならないと規定している。


<h2>認証</h2>
現在、HTTP1.1では、「Basic認証」と「Digest認証」がある。
あるリソースにアクセス制御がかかっている場合、
ステータスコード 401とWWW-Authenticateヘッダを利用してクライアントにリソースへのアクセスに必要な認証情報を通知する。

```
DELETE/test HTTP1.1
Host example.jp
```

レスポンス
```
HTTP1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Example.jp"
```

WWW-Authenticateを設けることでクライアントがサーバが提供する認証方式を理解し、
その方式に従った、かたちで認証情報を送る。

 上記では、Basic認証で、realmはURI空間を指す。
※URI空間とは、「仮定でURI空間を="https:://www.example.jp/foo"」とおくと、
以下のURIが全てURI空間に属することになり、クライアントが同等のURI空間に関しては、
同じ認証方式を取り入れることから、401 Unauthorizedがかえるのを避けることができる。

<h3>Basic 認証</h3>
Basic認証は、ユーザとPWで認証する方式である。
ユーザとPWをAuthorizationのヘッダに入れてリクエストを送信する。

```
Delete /test HTTP1.1
Host: example.jp
Authorization: Basic dxnkadvcnodsvf==
```
AUthorizationヘッダの内容は、」認証方式の後に、ユーザ名とPWを「:」で連結し
Base64エンコードした文字列である。Base64コードはデコードすることが簡単である
すなわち、ユーザ名とPWが平文でネットワーク上を流れていることを意味する。
Basic認証を使う場合、**セキュリティ**を考慮しなければいけない。
その程度のセキュリティであれば、問題ないだが、
どうしても、Basic認証を　使い、セキュリティ強度を高めたい場合は
**SSL**や**TLS**を使ってHTTPS通信し通信路上で暗号化するのかを検討しなければいけない。

<h3>Digest認証</h3>

Basic認証より、セキュアな認証である。Digest認証は、メッセージダイジェストの略で、
あるメッセージに対して**ハッシュ関数**を適用した結果のハッシュ値である。
Digest認証は、Basic認証よりも少々複雑な流れで認証を行う。Digest認証でも、
クライアントはまず認証なしでリクエストを送信する。結果として認証が失敗し、401 Unauthorizedが返ってくるだろう。

```
リクエスト
DELETE /test HTTP1.1
Host: example.jp
```

```
レスポンス
HTTP1.1 401 Unauthorized
WWW-Authenticate: Digest realm="example.jp", norce="dcmaljceoapsjcdiu90342u", qop="auth", opaque="76uq9deq8deueqt7qdegtq"
```

<h5>Digest認証のメリットとデメリット</h5>
    Basic認証とは異なり、PWを盗まれる危険性はありません。またDigest認証ではサーバにPWそのものを補完するのではなく、**ハッシュ値**を補完すれば良い。ーセキュリティリスクを下げる大きな優位点である。
ただし、Digest認証は、PWを暗号化するだけなので、メッセージを暗号化したい場合はBasic認証と同様に**HTTPS**を利用しよう。

    Basic認証は同じURI空間のリソースであればクライアントは一度認証すれば2回目以降**自動的に***ユーザ名とPWを送れました。しかし、Digest認証は、サーバからnonce(一度だけ使われる数字→リクエストごとに変化する)がなければ、クライアント側で*ダイジェスト*を計算できないため,リクエストのたびに401　を返すことになる。

これは、クライアント側から見れば、ややこしいものであり、普及されにくい要因の一つであるだろう。
<h3>9.9　キャッシュとは</h3>

キャッシュは、サーバから取得したデータをローカルストレージに蓄積し、再利用する仕組みのことである。クライアントに蓄積したキャッシュは、クライアントがアクセスした際に再利用できる仕組みのことである。
クライアントがキャッシュ利用できるか否かについては、取得した際にヘッダを見て判断します。リソースがキャッシュ可能か、有効期限がいつまでなのかどうかについては、「ヘッダの」
**Pragma**, **Expires**, **Chace Control**ヘッダを用いて探します。

<h4>Prgma --キャッシュを抑制する</h4>

Prgmaヘッダに明記できるのは、no-chaceのみです。これは、
リソースをキャッシュできない意味を指し示す。
そのため、リソースへアクセスしたい場合は、サーバへ再度アクセスする必要がある。

Expires --キャッシュの有効期限を示す
Expiresはキャッシュの有効期限を示す。

```
Expires: Thu, 11, May, 2020 15:00:00 GMT
```
※2020 5,11までキャッシュが有効期限であることを指す。このリソースを変更する可能性がない場合は永久にキャッシュ可能であることを示したくなるが、そのような場合でも
Expiresヘッダに最長で約1年ごの日時を入れることを推奨している。

::: note warn

PragmaととExpiresはHTTP1.0仕様

:::

<h4>Cache-Control --詳細なキャッシュ方法を指定する</h4>
PragmaとExpiresヘッダはHTTP1.0画定義したヘッダである。簡単なキャッシュは実現できるが、複雑な指定は実現できない。より複雑なキャッシュを実現したい場合はHTTP1.1では
**Cache-Controlヘッダ**を使う。PragmaとExpiresヘッダの代用は可能である。

EX
```
Expires: no-cache
```
と
```
Cache-Control: no-cache
```
は等しい。
Expiresでは、**絶対時間で**付与していたが、Cache-Controlでは**相対時間**
で有効時間を設定可能である。
Cache-Controlヘッダでは、他にもさまざまな識別子がある。これらにより、細かく設定を制御できる。

<h3>キャッシュ用ヘッダの使い方</h3>
キャッシュ用のヘッダは3つある。-Pragma, Expires, Cache-Control。
使い分けは以下の通りである。

1 .
キャッシュをさせない場合はPragmaとCache-Cotrolの「no-cache」を同時に指定する

2 .
キャッシュの有効時間が明確に決まっている場合はExpiresを指定する

3 .
キャッシュの有効時間を相対的に指定したい場合はCache-Controlのmax-ageで相対時間を指定する

<h3>条件付きGet</h3>
クライアントがExpiresやCache-Controlを検証した結果、ローカルキャッシュをそのまま再利用できないと判断した場合でも条件付きGetを送信すれば再利用できる可能性がある。

:::note warn

条件付きGetは、「ブラウザがリクエストを送信する際に、サーバに対してコンテンツが更新されているかどうかを尋ね、更新されていなければブラウザが持つキャッシュを利用させる仕組み」です。

:::

<h4>if-Modified-Since --リソースの更新日時を限定する</h4>

```
| Get               | /test HTTP1.1                 |     | 
| Host:             | example.jp                    |     | 
| if-Modified-Since | Thu, 11 May 2010 16:00:00 GMT |     | 
```
このリクエストは、ローカルキャッシュの更新日時が2010 5 11 16時 ちょうどであることを示しています。サーバー上のリソースがこれ以上、変更されていなければ、サーバ次のレスポンスを返す。

```
| -------------- | ----------------------------------- | --- | 
| HTTP 1.1       | 304 Not Modified                    |     | 
| Content-Type:  | application/xhtml+xml charset=utf-8 |     | 
| Last-Modified: | Thu, 11 May 2010 16:00:00 GMT       |     | 
```

304は条件付きGetへのレスポンスで、サーバ上のリソースを変更していないことを知らせるステータスコードである。リソースの更新日時はLast-Modifiedヘッダで確認できます。レスポンスには、ボディが含まれていないため
ネットワーク帯域を節約できる。

<h4>if-None-Match --リソースのETagを条件にする</h4>
if-Modified-Sinceヘッダとlast-Modifiedヘッダによる条件つきGetは便利だが、「時計を持っていないサーバ」や「ミリ秒単位で変更される可能性のあるリソース」には利用できない。その場合に用いるのが、「if-NOne-Modifiedヘッダ」と「ETagヘッダ」である。

```
| ---------------- | --------------- | --- | 
| Get              | /test2 HTTP 1.1 |     | 
| Host             | example.jp      |     | 
| If-None-Modified | ab3322028       |     | 
```

If-Modified-SinceとIf-Not-Modifiedは一見、類似しているように見えるが
実際は異なる。
If-Modified-Sinceは、「指定した日時以降に更新されれば」、に対してIf-None-Modifiedは「指定した値にマッチしなければ」という意味合いである。
If-None=modifieidに指定した値は、**キャッシュしてある**りおソースのETagヘッダの値である。

上記の条件付きGetの結果、サーバ上のリソースが更新されていなければ次のレスポンスが返る。

```
| ------------- | ------------------------------------ | --- | 
| HTTP 1.1      | 304 Not Modified                     |     | 
| Content-Type: | application/xhtml+xml; charset=utf-8 |     | 
| Etag:         | ab3322028                            |     | 
```

Etagはリソース更新状態を比較するためだけに使う文字列。変更する際に、文字列が変化されればどのような文字列でも構わない。