HTTP キャッシュ - HTTP

HTTP キャッシュ
==========

概要
--

HTTP キャッシュは、リクエストに関連付けられたレスポンスを格納し、格納されたレスポンスを後続のリクエストのために再利用します。

再利用にはいくつかの利点があります。まず、リクエストを元サーバーに届ける必要がないため、クライアントとキャッシュの距離が近いほど、レスポンスが速くなります。ほとんどの例は、ブラウザー自身がブラウザーのリクエストのキャッシュを格納するものです。

また、レスポンスが再利用可能な場合、元のサーバーはリクエストを処理する必要がありません。つまり、リクエストを解釈してルーティングしたり、クッキーに基づいてセッションを復元したり、結果をDBに問い合わせたり、テンプレートエンジンをレンダリングしたりする必要がありません。これによりサーバーの負荷が軽減されます。

キャッシュを適切に管理運営することは、システムを健全にするためにとても重要です。

キャッシュの種類
--------

HTTP Caching 仕様書では、キャッシュには大きく分けて 2 つの種類があります。**プライベートキャッシュ**と**共有キャッシュ**です。

### プライベートキャッシュ

プライベートキャッシュとは、特定のクライアント（通常はブラウザーキャッシュ）に結びついたキャッシュのことです。格納されるレスポンスは他のクライアントと共有されないので、プライベートキャッシュはそのユーザー用にパーソナライズされたレスポンスを格納することができます。

一方、プライベートキャッシュ以外のキャッシュにパーソナライズされたコンテンツが格納されると、他のユーザーがそのコンテンツを取得できる可能性があり、意図しない情報漏洩が発生する可能性があります。

レスポンスにパーソナライズされたコンテンツを含み、プライベートキャッシュにのみ格納したい場合は `private` ディレクティブを指定しなければなりません。

```http
Cache-Control: private
```

パーソナライズされたコンテンツは通常クッキーによって制御されますが、クッキーの存在が常にプライベートであることを示すとは限らないため、クッキーだけでレスポンスがプライベートになるわけではありません。

レスポンスに `Authorization` ヘッダーがある場合、プライベートキャッシュには格納されない（`public` を指定しない限り、共有キャッシュに格納される）ことに注意してください。

### 共有キャッシュ

共有キャッシュはクライアントとサーバーの間に格納され、ユーザー間で共有できるレスポンスを格納するために使用されます。共有キャッシュはさらに、**プロキシーキャッシュ** と **マネージドキャッシュ** に分類されます。

#### プロキシーキャッシュ

アクセス制御する機能に加えて、一部のプロキシーはネットワークからのトラフィックを削減するためにキャッシュを実装しています。これは通常サービス開発者によって管理されるものではないので、適切な HTTP ヘッダーなどによって 制御しなければなりません。しかし、過去には時代遅れのプロキシーキャッシュ実装、すなわち HTTP キャッシュ標準を正しく理解していない実装などが、開発者に問題を発生させることが多くありました。

以下のような**キッチンシンクヘッダー**を用いて、`no-store` のような現在の HTTP Caching 仕様書のディレクティブを理解しない、「古くて更新されていないプロキシーキャッシュ」の実装を回避しようします。

```http
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
```

しかし、近年 HTTPS が一般的になり、クライアント/サーバ間の通信が暗号化されるようになったため、 経路上のプロキシーキャッシュはレスポンスをトンネリングすることしかできず、 キャッシュとして振る舞うことができない場合が多くなっています。そのような場合は、レスポンスを見ることすらできないので、時代遅れのプロキシーキャッシュ実装を心配する必要はありません。

他にも、 TLS ブリッジプロキシーが、組織が管理する認証局 (CA) の資格情報を PC にインストールすることで、中間者 (person-in-the-middle) 的にすべての通信を復号し、アクセス制御などを行う場合、レスポンスの内容を見たり、キャッシュしたりすることが使用可能です。ただし、近年は CT (certificate transparency) が普及し、ブラウザーによっては SCT (signed certificate timestamp) で発行された証明書しか許可しないものもあるため、このメソッドでは企業ポリシーを適用する必要があります。このような制御された環境では、プロキシーキャッシュが「古くて更新されない」ことを心配する必要はありません。

#### マネージドキャッシュ

マネージドキャッシュは、サービス開発者が元サーバの負荷を分散し、コンテンツを効率的に開発するために明示的に展開するものです。例えば、リバースプロキシー、CDN、キャッシュ API と組み合わせたサービスワーカーなどがあります。

マネージドキャッシュの特性は、展開する製品によって異なります。ほとんどの場合、`Cache-Control` ヘッダーと自分自身で設定ファイルやダッシュボードを通してキャッシュの動作を制御することができます。

例えば、HTTP キャッシュ仕様書では、基本的にキャッシュを明示的に削除する方法は定義されていません。しかし、マネージドキャッシュでは、ダッシュボード操作や API 呼び出し、再起動などによって、格納されたレスポンスをいつでも削除することができます。これにより、より積極的なキャッシュ戦略が可能になります。

標準 HTTP キャッシュ仕様書のプロトコルを無視して、明示的な操作を行うことも使用可能です。例えば、次の例はプライベートキャッシュやプロキシキャッシュをオプトアウトし、自分自身で管理キャッシュにのみキャッシュする戦略を使用するように指定することができます。

```http
Cache-Control: no-store
```

例えば、Varnish Cache は VCL （Varnish Configuration Language、DSL の一種）ロジックを使用してキャッシュストレージを処理しますが、サービスワーカーとキャッシュ API との組み合わせにより、JavaScript でそのロジックを作成することができます。

つまり、マネージドキャッシュが意図的に `no-store` ディレクティブを無視したとしても、それを「標準に準拠していない」とみなす必要はないということです。キッチンシンクヘッダーの使用を避け、使用している管理キャッシュ機構のドキュメントを注意深く読み、使用する機構で指定された方法で適切にキャッシュを制御していることを確実に保持することです。

なお、CDNによっては、そのCDNに対してのみ有効なヘッダーを自分自身で提供しているものもあります（`Surrogate-Control` など）。現在、これらを標準化するために `CDN-Cache-Control` ヘッダーを定義する作業が進められています。

![キャッシュの種類](/ja/docs/Web/HTTP/Caching/type-of-cache.png)

ヒューリスティックキャッシュ
--------------

HTTP は可能な限りキャッシュするように設計されているので、`Cache-Control` が指定されていなくても、ある条件が満たされればレスポンスは格納されて再利用されます。これは**ヒューリスティックキャッシュ**と呼ばれます。

例えば、次のようなレスポンスを見てみましょう。このレスポンスの最終更新は 1 年前です。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT

<!doctype html>
…
```

1 年間更新されなかったコンテンツは、その後しばらく更新されないことがヒューリスティックに知られています。そのため、クライアントはこのレスポンスを（`max-age` がないにもかかわらず）格納し、しばらく再利用します。どのくらいの期間再利用するかは実装次第ですが、仕様では格納した後の時間の約 10 %（この場合は 0.1 年）を推奨しています。

ヒューリスティックキャッシュは `Cache-Control` 対応が広く採用される以前の回避策であり、基本的にすべてのレスポンスは `Cache-Control` ヘッダーを明示的に指定する必要があります。

age に基づく新鮮さと古さ
--------------

格納される HTTP レスポンスには、**新鮮** (fresh) と**古い** (stale) の 2 つの状態があります。新鮮な状態は通常、レスポンスがまだ有効で再利用できることを示し、古い状態はキャッシュされたレスポンスがすでに期限切れであることを意味しています。

レスポンスがいつ新鮮で、いつ古くなったかを判断する基準は **age** です。 HTTP では、 age はレスポンスが生成されてからの経過時間です。これは他にもキャッシュ機構における TTL に似ています。

次のレスポンス例を見てみましょう（604800 秒は 1 週間）。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=604800

<!doctype html>
…
```

この例のレスポンスが格納されたキャッシュは、レスポンスが生成されてからの経過時刻を計算し、その結果をレスポンスの *age* として使用します。

例えば、レスポンスの `max-age` の意味は以下の通りです。

* レスポンスの age が 1 週間未満である場合、そのレスポンスは新鮮です。
* レスポンスの age が 1 週間を超える場合、そのレスポンスは古いです。

格納されたレスポンスが新鮮である限り、クライアントのリクエストを履行するために使用されます。

レスポンスが共有キャッシュに格納されるとき、クライアントにレスポンスの age を通知する必要があります。例えば、共有キャッシュがレスポンスを 1 日間格納された場合は、次の例のようになります。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=604800
Age: 86400

<!doctype html>
…
```

そのレスポンスを受け取ったクライアントは、レスポンスの `max-age` と `Age` の差である残り 518400 秒の間、そのレスポンスが新鮮であることを受け取ります。

有効期限または max-age
---------------

HTTP/1.0 では、鮮度は `Expires` ヘッダーを使用して指定 していました。

`Expires` ヘッダーは、経過時間を指定するのではなく、明示的な時刻を使用してキャッシュの有効期間を指定します。

```http
Expires: Tue, 28 Feb 2022 22:22:22 GMT
```

しかし、この時刻形式は解釈が難しく、多くの実装バグが見つかり、システムクロックを意図的にずらすことで問題を誘発する可能性がありました。そのため、HTTP/1.1 では `Cache-Control` に経過時間を指定する `max-age` が採用されました。

`Expires` と `Cache-Control: max-age` の両方が利用できる場合は、 `max-age` を優先するように定義されています。そのため、HTTP/1.1 が広く使用されるようになった現在では `Expires` を提供する必要はありません。

Vary
----

レスポンスを判別する方法は、基本的に URL に基づいています。

![keyed with url](/ja/docs/Web/HTTP/Caching/keyed-with-url.png)

しかし、同じ URL を持っていてもレスポンスのコンテンツが常に同じとは限りません。特にコンテンツネゴシエーションが行われた場合、サーバからのレスポンスは `Accept`、`Accept-Language`、`Accept-Encoding` リクエストヘッダーの値によって変わる可能性があります。

例えば、`Accept-Language: en` ヘッダーで返されてキャッシュされた英語のコンテンツに対して、`Accept-Language: ja` リクエストヘッダーがあるリクエストに対してキャッシュされたレスポンスを再利用することは望ましくありません。この場合、"`Accept-Language`" を `Vary` ヘッダーの値に追加することで、レスポンスが言語に基づいて別個にキャッシュされるようにすることができます。

```http
Vary: Accept-Language
```

これにより、キャッシュはレスポンス URL と `Accept-Language` リクエストヘッダーの合成に基づいて生成されます。

![URL と言語がキーになる例](/ja/docs/Web/HTTP/Caching/keyed-with-url-and-language.png)

また、（例えばレスポンシブデザインのために）ユーザーエージェントに基づいてコンテンツの最適化を提供している場合、 `Vary` ヘッダーの値に "`User-Agent`" を含めることができます。しかし、一般的に `User-Agent` リクエストヘッダには非常に多くのバリエーションがあり、キャッシュが再利用される可能性を大幅に縮小します。そのため、可能であれば `User-Agent` リクエストヘッダーに基づくのではなく、機能検出に基づいて動作を変化させる方法を検討してください。

キャッシュされたパーソナライズされたコンテンツが他に再利用されるのを防ぐために、クッキーを使用するアプリケーションでは、`Vary`にクッキーを指定する代わりに `Cache-Control: private` を指定する必要があります。

検証
--

古くなったレスポンスはすぐには破棄されません。HTTPには、元のサーバーに問い合わせることで、古いレスポンスを新しいものに変換する仕組みがあります。これは**検証**、または**再認証**と呼ばれます。

検証は `If-Modified-Since` または `If-None-Match` リクエストヘッダーを含む**条件付きリクエスト**を使用することで行われます。

### If-Modified-Since

以下のレスポンスは 22:22:22 に生成され、 `max-age` は 1 時間なので、 23:22:22 まで新鮮であることがわかります。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600

<!doctype html>
…
```

23:22:22 になると、レスポンスは古くなり、キャッシュを再利用できなくなります。そのため、下記のリクエストはクライアントが `If-Modified-Since` リクエストヘッダーを持つリクエストを送信し、指定した時刻以降に変更があったかどうかをサーバーに問い合わせることを示しています。

```http
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT
```

コンテンツが指定した時刻から変更されていない場合、サーバーは `304 Not Modified` というレスポンスを返します。

このレスポンスは「変更されていない」ことを示すだけなので、レスポンス本体はありません。ステータスコードだけですので、転送サイズは非常に小さくなります。

```http
HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2022 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600
```

そのレスポンスを受信すると、クライアントは格納される古いレスポンスを新しいものに戻し、残りの 1 時間の間に再利用することができます。

サーバーはオペレーティングシステムのファイルシステムから更新時刻を取得することができ、静的ファイルを提供する場合には相対的に容易です。しかし、いくつかの問題があります。例えば、時刻形式が複雑で解釈しにくい、分散サーバーではファイル更新時刻の同期が取りにくいなどです。

このような問題を解決するために、 `ETag` レスポンスヘッダーが標準化されました。

### ETag/If-None-Match

`ETag` レスポンスヘッダーの値は、サーバーが生成する任意の値です。サーバーがどのように値を生成しなければならないかという制限はないので、サーバーはどのような意味に基づいて値を設定しても自由です。例えば、本体のコンテンツのハッシュやバージョン番号などです。

例えば、 `ETag` ヘッダーにハッシュ値を用い、 `index.html` リソースのハッシュ値が `33a64df5` の場合、レスポンスは以下のようになります。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600

<!doctype html>
…
```

そのレスポンスが古かった場合、クライアントはキャッシュされたレスポンスの `ETag` レスポンスヘッダーの値を受け取り、それを `If-None-Match` リクエストヘッダーに入れ、リソースが変更されたかどうかをサーバーに問い合わせます。

```http
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "33a64df5"
```

リクエストされたリソースの `ETag` ヘッダーの値がリクエストの `If-None-Match` の値と同じ場合、サーバーは `304 Not Modified` を返します。

しかし、リクエストされたリソースがこれで異なる `ETag` 値を持つようになったとサーバが判断した場合、サーバは代わりに `200 OK` とリソースの最新バージョンで応答します。

**メモ:** RFC9110 では、できれば `200` レスポンスに対して `ETag` と `Last-Modified` の両方を送信することを推奨しています。
 キャッシュの再検証の際に、 `If-Modified-Since` と `If-None-Match` の両方が存在する場合は、 `If-None-Match` を優先します。
 キャッシュだけを考えているのであれば、 `Last-Modified` は不要だと思うかもしれません。
 しかし、 `Last-Modified` はキャッシュに有益なだけではなく、コンテンツ管理 (CMS) システムが最終更新時刻を表示したり、クローラーがクロール頻度を調整したり、他にも様々な目的で使用する標準 HTTP ヘッダーです。
 そのため、 HTTP エコシステム全体を考慮すると、 `ETag` と `Last-Modified` の両方を提供した方が良いでしょう。

### 強制的な再検証

レスポンスを再利用せず、常に最新のコンテンツをサーバーから取得したい場合は、 `no-cache` ディレクティブを使用して強制的に検証することができます。

レスポンスに `Cache-Control: no-cache` を `Last-Modified` と `ETag` とともに追加することで、下記で示すように、リクエストされたリソースが更新されていればクライアントは `200 OK` レスポンスを受け取り、更新されていなければ `304 Not Modified` レスポンスを受け取ります。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
ETag: deadbeef
Cache-Control: no-cache

<!doctype html>
…
```

`max-age=0`と `must-revalidate` の組み合わせは `no-cache` と同じ意味を持つとよく言われています。

```http
Cache-Control: max-age=0, must-revalidate
```

`max-age=0` はレスポンスが即座に古くなることを意味しており、 `must-revalidate` は古くなったレスポンスを再検証せずに再利用してはいけないことを意味しています。つまり、この組み合わせの意味は `no-cache` と同じです。

しかし、この `max-age=0` を使用することは、HTTP/1.1 より前の実装の多くが `no-cache` ディレクティブを処理することができなかったことの名残です。そのため、その制限に対処するために、回避策として `max-age=0` を使用していました。

しかし、これで HTTP/1.1 準拠のサーバが広く普及したため、 `max-age=0` と `must-revalidate` の組み合わせを使用する理由はなくなりました。

キャッシュしない
--------

`no-cache` ディレクティブはレスポンスを格納しないようにするのではなく、再検証せずにレスポンスを再利用しないようにします。

レスポンスをキャッシュに格納したくない場合は、 `no-store` を使用してください。

```http
Cache-Control: no-store
```

しかし、一般的に、「キャッシュしない」という要件は、実際には以下のような設定になります。

* プライバシー保護のため、特定のクライアント以外にレスポンスを格納されたくない場合。
* 常に最新の情報を提供したい場合。
* 時代遅れの実装であり、何が起こるか分からない場合。

このような状況では、 `no-store` は常に適切なディレクティブとは限りません。

次の節では、その状況をより詳しく見ていきます。

### 他の人と共有しないようにする

パーソナライズされたコンテンツを含むレスポンスが、予期せずキャッシュの他のユーザーに見えてしまうのは問題です。

このような場合、`private` ディレクティブを使用することで、パーソナライズされたレスポンスは特定のクライアントにのみ格納され、他のキャッシュユーザーに漏れることはなくなります。

```http
Cache-Control: private
```

このような場合、 `no-store` を指定したとしても、 `private` も指定しなければなりません。

### 常に最新のコンテンツを提供する

`no-store` ディレクティブはレスポンスが格納されることを防ぎますが、同じ URL に対して既に格納されているレスポンスを削除することはありません。

言い換えれば、特定の URL に対して古いレスポンスが既に格納されている場合、 `no-store` を返しても古いレスポンスが再利用されることはありません。

しかし、`no-cache` ディレクティブは格納されたレスポンスを再利用するために、 クライアントに検証リクエストを送らせます。

```http
Cache-Control: no-cache
```

サーバーが条件付きリクエストに対応していない場合は、クライアントに毎回サーバーにアクセスするように強制し、常に `200 OK` で最新のレスポンスを取得することができます。

### 古い実装への対応

`no-store` を無視する古い実装を回避するために、以下のようなキッチンシンクのようなヘッダーが使用されているかもしれません。

```http
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
```

推奨 されている方法は、このような古い実装に対処するために代替手段として `no-cache` を使用することです。また、`no-cache` が最初から指定されていても、サーバーは常にリクエストを受け取るので問題ありません。

もし気になるのが共有キャッシュであれば、 `private` も追加することで、意図しないキャッシュを防ぐことができます。

```http
Cache-Control: no-cache, private
```

### `no-store` で失われるもの

`no-store` を追加することは、キャッシュをオプトアウトするために正しい方法だと思うかもしれません。

しかし、`no-store` を自由に許可することは推奨されません。ブラウザーのバック/フォワードキャッシュを含めるために、 HTTP とブラウザーが持つ多くの利点を失ってしまうからです。

したがって、ウェブプラットフォームの全機能の利点を享受するには、 `no-cache` を `private` と組み合わせて使用することを推奨します。

再読み込みと強制再読み込み
-------------

検証はレスポンスだけでなく、リクエストに対しても行うことができます。

**再読み込み** (reload) と**強制再読み込み** (force reload) は、ブラウザー側から実行される検証の一般的な例です。

### 再読み込み

ウィンドウの破損からの回復やリソースの最新バージョンへの更新のために、ブラウザーはユーザーに再読み込み機能を提供しています。

ブラウザーの再読み込み中に送信される HTTP リクエストを簡略化すると、以下のようになります。

```http
GET / HTTP/1.1
Host: example.com
Cache-Control: max-age=0
If-None-Match: "deadbeef"
If-Modified-Since: Tue, 22 Feb 2022 20:20:20 GMT
```

（Chrome、Edge、Firefox からのリクエストは上記のものにとてもよく似ています。 Safari からのリクエストは多少異なります。）

リクエストの `max-age=0` ディレクティブは、「age が 0 以下のレスポンスの再利用」を指定します。つまり、事実上、中間で格納されたレスポンスは再利用されません。

その結果、リクエストは `If-None-Match` と `If-Modified-Since` によって検証されます。

この動作はフェッチ標準でも定義されており、JavaScript でキャッシュモードを `no-cache` に設定して `fetch()` を呼び出すことで再現することができます（この場合 `reload` は正しいモードではないことに注意してください）。

```js
// メモ: "reload" は通常の再読み込みには正しいモードではありません。 "no-cache" です。
fetch("/", { cache: "no-cache" });
```

### 強制再読み込み

ブラウザーがリロード時に `max-age=0` を使用するのは、 HTTP/1.1 より前の古い実装の多くが `no-cache` を理解していなかったためです。しかし、 `no-cache` はこの用途ではこれで問題なく、**強制再読み込み**はキャッシュされたレスポンスをバイパスするための追加の方法です。

ブラウザーが **強制再読み込み**しているときの HTTP リクエストは以下のようになります。

```http
GET / HTTP/1.1
Host: example.com
Pragma: no-cache
Cache-Control: no-cache
```

（Chrome、Edge、Firefox からのリクエストは上記のものにとてもよく似ています。 Safari からのリクエストは多少異なります。）

これは `no-cache` による条件付きリクエストではないので、元のサーバーから `200 OK` を取得することは確実です。

この動作はフェッチ標準でも定義されており、JavaScript でキャッシュモードを `reload` にして `fetch()` を呼び出すことで再現できます（`force-reload` ではないことに注意してください）。

```js
// メモ: "reload" （"no-cache" ではない）は「強制再読み込み」で正しいモードです。
fetch("/", { cache: "reload" });
```

### 再検証の回避

変更されることのないコンテンツには、キャッシュバスティング、つまり、リクエスト URL にバージョン番号やハッシュ値などを含めることにより、長い `max-age` を指定してください。

しかし、ユーザーが再読み込みすると、たとえサーバーがそのコンテンツが不変であることを知っていたとしても、再検証リクエストが送られます。

これを防ぐために、`immutable` ディレクティブを使用して、コンテンツは変更されないので再検証は不要であることを明示することができます。

```http
Cache-Control: max-age=31536000, immutable
```

これにより、再読み込み時の不要な再検証を防ぐことができます。

このディレクティブを実装する代わりに、 Chrome は実装を変更し、サブリソースの再読み込み中に再検証を行わないようにしました。

格納されたレスポンスの削除
-------------

長い `max-age` で格納されているレスポンスを削除する方法は基本的にありません。

例えば、以下のように `https://example.com/` からのレスポンスが格納されていたとします。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: max-age=31536000

<!doctype html>
…
```

サーバー上で有効期限が切れたレスポンスを上書きしたいと思うかもしれませんが、レスポンスが格納されると、キャッシュによりそれ以上のリクエストがサーバーに到達しないため、サーバー側でできることはまだありません。

詳細仕様で言及されているメソッドのひとつに、 `POST` のような安全でないメソッドで同じ URL のリクエストを送るというものがありますが、通常多くのクライアントにとって意図的に行うことは困難です。

`Clear-Site-Data:cache` ヘッダーと値の仕様もありますが、すべてのブラウザーが対応しているわけではありません。また、使用されている場合でも、ブラウザーのキャッシュにのみ影響し、中間キャッシュには影響を及ぼしません。

したがって、格納されるレスポンスはユーザーが手動で再読み込み、強制再読み込み、履歴クリアの操作を行わない限り、その `max-age` 期間は残るものとみなされます。

キャッシュはサーバーへのアクセスを削減し、サーバーがその URL の制御を失うことを意味しています。サーバーが URL の制御を失いたくない場合、例えばリソースが頻繁に更新されるような場合、 `no-cache` を追加して、サーバが常にリクエストを受け取り、意図するレスポンスを送信できるようにする必要があります。

リクエストの折りたたみ
-----------

共有キャッシュは主に元のサーバーの前にあり、元のサーバーへのトラフィックを削減することを意図しています。

したがって、複数の同じリクエストが同時に共有キャッシュに到着した場合、 中間キャッシュはそれ自身に代わって単一のリクエストをオリジンに転送し、 その結果をすべてのクライアントに再利用することがあります。これは**リクエストの折りたたみ**と呼ばれます。

リクエストの折りたたみはリクエストが同時に到着したときに起こるので、レスポンスに `max-age=0` や `no-cache` が指定されたとしても、再利用されます。

レスポンスが具体的なユーザーにパーソナライズされていて、折りたたみ時に共有されたくない場合は `private` ディレクティブを追加してください。

![リクエストの折りたたみ](/ja/docs/Web/HTTP/Caching/request-collapse.png)

良くあるキャッシュパターン
-------------

`Cache-Control` の仕様には多くのディレクティブがあり、すべてを理解するのは難しいかもしれません。しかし、ほとんどのウェブサイトは一握りのパターンの組み合わせでカバーすることができます。

この章では、キャッシュを設計する際の一般的なパターンを記述します。

### 既定の設定

上記のように、キャッシュの既定値（つまり `Cache-Control` のないレスポンス）は単純に「キャッシュしない」ではなく、いわゆる「ヒューリスティックキャッシュ」に従った暗黙的なキャッシュです。

ヒューリスティックキャッシュを避けるためには、すべてのレスポンスに既定値の `Cache-Control` ヘッダーを明示的に付与することが推奨されます。

既定値では常に最新バージョンのリソースを転送するように保持するために、既定値の `Cache-Control` に `no-cache` を含めるのが一般的です。

```http
Cache-Control: no-cache
```

また、サービスワーカースクリプトが Cookie や他のログインメソッドを実装しており、コンテンツがユーザーごとにパーソナライズされている場合は、他のユーザーと共有されないように `private` も指定されなければなりません。

```http
Cache-Control: no-cache, private
```

### キャッシュの破棄

キャッシュと最もうまく動作するリソースは、コンテンツが変更されることのない静的で不変なファイルです。そして、変更されるリソースについては、コンテンツが変更されるたびに URL を変更し、 URL 単位を詳しくキャッシュできるようにするのが一般的なベストプラクティスです。

例えば、次のような HTML を考えてみましょう。

```html
<script src="bundle.js"></script>
<link rel="stylesheet" href="build.css" />
<body>
  hello
</body>
```

現代のウェブ開発では、開発の進捗に応じて JavaScript や CSS のリソースが頻繁に更新されます。また、クライアントが使用する JavaScript や CSS リソースのバージョンがずれていると、表示が崩れてしまいます。

そのため、上記の HTML では `bundle.js` と `build.css` を `max-age` でキャッシュすることが難しくなっています。

従って、 JavaScript と CSS をバージョン番号やハッシュ値に基づいて変更する部分を含めた URL で提供することができます。その方法のいくつかを下記に示します。
```

# ファイル名にバージョンを入れる
bundle.v123.js

# クエリーにバージョンを入れる
bundle.js?v=123

# ファイル名にハッシュを入れる
bundle.YsAIAAAA-QG4G6kCMAMBAAAAAAAoK.js

# クエリーにハッシュを入れる
bundle.js?v=YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

キャッシュは URL に基づいてリソースを判別するので、リソースが更新されたときに URL が変更されると、キャッシュは再利用されません。

```html
<script src="bundle.v123.js"></script>
<link rel="stylesheet" href="build.v123.css" />
<body>
  hello
</body>
```

その設計であれば、 JavaScript も CSS リソースも長時間キャッシュすることができます。では、 `max-age` はどれくらいの長さに設定するべきなのでしょうか？ QPACK 仕様がその答えを提供しています。

QPACK は HTTP ヘッダーフィールドを圧縮するための標準であり、一般的に使用するフィールド値の表が定義されています。

一般的に使用するキャッシュヘッダーの値を下記に示します。
```

36 cache-control max-age=0
37 cache-control max-age=604800
38 cache-control max-age=2592000
39 cache-control no-cache
40 cache-control no-store
41 cache-control public, max-age=31536000
```

これらの番号付きオプションのいずれかを選択すると、 HTTP3 で転送するときに値を 1 バイトに圧縮することができます。

番号 `37`, `38`, `41` は 1 週間、 1 ヶ月、 1 年の期間です。

キャッシュは新しい項目が保存されると古い項目を除去するので、 `max-age` が 1 週間に設定されていたとしても、 1 週間後に格納されるレスポンスが存在する確率はそれほど高くありません。したがって、実際にはどちらを選んでもあまり違いはありません。

`41` 番が最も長い `max-age` （1 年）を持っていますが、 `public` が付いていることに注意してください。

`public` 値は `Authorization` ヘッダーを表示している場合でも、レスポンスを保存できるようにする効果があります。

**メモ:** `public` ディレクティブは `Authorization` ヘッダーが設定されたときにレスポンスを格納する必要がある場合にのみ使用してください。
 `max-age` が指定されている限り、レスポンスは共有キャッシュに格納されるからです。

そのため、レスポンスが基本的な認証でパーソナライズされている場合、 `public` があると問題が発生する可能性があります。もしそれが心配なら、 2 つ目の値である `38` （1 ヶ月）を選ぶことができます。

```http
# bundle.v123.js へのレスポンス

# 認証によりパーソナライズされることがない場合
Cache-Control: public, max-age=31536000

# 確信が持てない場合
Cache-Control: max-age=2592000
```

### 検証

再読み込み時にリソースを再送信する必要がないように、 `Last-Modified` ヘッダーと `ETag` ヘッダーを設定することを忘れないでください。ビルド済みの静的ファイルに対してこれらのヘッダーを生成するのは簡単です。

ここでの `ETag` 値はファイルのハッシュです。

```http
# bundle.v123.js へのレスポンス
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

さらに、 `immutable` を追加することで、再読み込み時の検証を防ぐことができます。

組み合わせた結果を下記に示します。

```http
# bundle.v123.js
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Length: 1024
Cache-Control: public, max-age=31536000, immutable
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

**キャッシュ破棄**は、コンテンツが変更されたときに URL を変更することで、長期間にわたってレスポンスをキャッシュ可能にするテクニックです。このテクニックは、画像などのすべてのサブリソースに適用できます。

**メモ:** `immutable` と QPACK を使用することを評価する場合：
 もし `immutable` が QPACK が提供する定義済みの値を変更することを懸念しているのであれば、 `Cache-Control` 値を 2 行に分割することで、`immutable` の部分を別個の文字にエンコードすることができると考えることができます。ただし、これは特定の QPACK 実装が用いるエンコーディングアルゴリズムに依存します。

```http
Cache-Control: public, max-age=31536000
Cache-Control: immutable
```

### 主要リソース

メインリソースはサブリソースと異なり、URLの装飾ができないため、キャッシュ破棄ができません。

次の HTML そのものが格納されている場合、サーバー側でコンテンツが更新されても最新版を表示することはできません。

```html
<script src="bundle.v123.js"></script>
<link rel="stylesheet" href="build.v123.css" />
<body>
  hello
</body>
```

その場合、 HTML を格納するためではなく、常に最新の状態にしたいだけなので、 `no-store` ではなく、 `no-cache` が適切でしょう。

さらに、 `Last-Modified` と `ETag` を追加することで、クライアントは条件付きのリクエストを送ることができるようになり、HTML に更新がない場合は `304 Not Modified` を返すことができるようになります。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: no-cache
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: AAPuIbAOdvAGEETbgAAAAAAABAAE
```

この設定はパーソナライズされていない HTML には適切ですが、例えばログイン後など、クッキーを使用してパーソナライズされるレスポンスには `private` を指定することを忘れないでください。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: no-cache, private
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: AAPuIbAOdvAGEETbgAAAAAAABAAE
Set-Cookie: \_\_Host-SID=AHNtAyt3fvJrUL5g5tnGwER; Secure; Path=/; HttpOnly
```

同じことは、`favicon.ico`、`manifest.json`、`.well-known`、キャッシュ破棄を使用して URL を変更できない API エンドポイントにも使用することができます。

ほとんどのウェブコンテンツは、前述した 2 つのパターンの組み合わせに応じた対応が可能です。

### マネージドキャッシュの詳細

前節で説明したメソッドでは、キャッシュ破棄を使用することでサブリソースを長時間キャッシュすることができますが、メインリソース（通常は HTML 文書）はキャッシュすることができません。

メインリソースのキャッシュが難しいのは、HTTP キャッシュ仕様の標準ディレクティブを使用するだけでは、サーバーでコンテンツが更新されたときにキャッシュの内容を積極的に削除する方法がないからです。

しかし、CDN やサービスワーカーなどのマネージドキャッシュを展開することで使用可能です。

例えば、API やダッシュボードの処理によってキャッシュの破棄が可能な CDN では、メインのリソースを格納し、サーバーで更新が発生した場合にのみ関連するキャッシュを明示的に破棄することで、より積極的なキャッシュ戦略が可能になります。

サービスワーカーは、サーバで更新が発生したときにキャッシュ API のコンテンツを削除できれば、同じことができます。

より詳しい情報は、 CDN のドキュメント化や サービスワーカーのドキュメント を参照してください。

関連情報
----

* RFC 9111: Hypertext Transfer Protocol (HTTP/1.1): Caching
* Caching Tutorial - Mark Nottingham


HTTP 条件付きリクエスト - HTTP

HTTP 条件付きリクエスト
==============

HTTP には*条件付きリクエスト*の概念があり、対象となるリソースと*検証子*の値とを比較することで、リクエストの結果や、成功か失敗かまでもが変化することがあります。このようなリクエストは、キャッシュの内容を検証して、無用な制御を避けたり、ダウンロードの再開の時などに文書の整合性を検証したり、サーバー上の文書をアップロードまたは変更するときに更新内容を失うことを避ける場合などに役立つことがあります。

原理
--

HTTP 条件付きリクエストは、特定のヘッダーの値に応じて異なる処理が行われるリクエストです。これらのヘッダーは前提条件を定義しており、リクエストの結果は前提条件に一致するか否かに応じて変わります。

リクエストで使用したメソッドや前提条件で使用したヘッダー一式によって、さまざまな動作が定義されています。

* 安全なメソッド、例えば `GET` などは、一般に文書を取得するメソッドであり、条件付きリクエストは関連する文書のみを返信するために利用することができます。これによって、帯域を節約します。
* 安全ではないメソッド、例えば `PUT` などは、一般に文書をアップロードするメソッドであり、条件付きリクエストは文書がサーバーに格納されているものと同じものに基づいたものである場合に限ってアップロードするようにするために利用することができます。
検証子
---

すべての条件ヘッダーは、サーバーに保存されているリソースが特定のバージョンに一致するか確認を試みます。このため、条件付きリクエストではリソースのバージョンを示す必要があります。リソース全体をバイト単位で比較することは不可能であり、常に望まれていることとは限らないので、リクエストはバージョンを記述する値を送信します。このような値は*検証子*と呼ばれ、二種類があります。

* 文書が最後に変更された日時である *last-modified* の日時
* *エンティティタグ*または *etag* と呼ばれる、各バージョンを一意に識別する不透明な文字列。

同じリソースのバージョンの比較は少々複雑です。状況によって、二種類の*確認方法*があります。

* 強い検証 (Strong validation) は、ダウンロードを再開するときなど、バイト単位の同一性が求められる場合に使用します。
* 弱い検証 (Weak validation) は、ユーザーエージェントが二つのリソースが同じであることを確認することだけが必要である場合に使用します。これは広告の違いやフッターの日付の違いなど、小さな違いがある場合も含みます。

検証の種類と使用される検証子は独立しています。 `Last-Modified` と `ETag` はどちらの種類の検証もできますが、サーバー側の実装の複雑さは異なります。 HTTP は既定で強い検証を使用し、弱い検証を使用するときはそれを指定します。

### 強い検証

強い検証は、比較対象のリソースがバイト単位で同一であることを保証します。これは一部の条件ヘッダーで必須、また他のヘッダーでは既定の要件です。強い検証はとても厳密であり、サーバーレベルで保証することが困難である場合もありますが、時には性能を犠牲にしても、データが失われていないことを常に保証します。

`Last-Modified` で強い検証のための一意な識別子を持つことは、とても困難です。多くの場合、リソースの MD5 ハッシュ（あるいはその派生物）を持つ `ETag` を使用します。

### 弱い検証

弱い検証は、内容が等価であるなら二つのバージョンの文書が等しいと見なされるという点で、強い検証と異なります。例えばフッターの日付だけ、あるいは広告だけが異なる二つのページは、弱い検証では*同一*であるとみなされますが、強い検証では異なるものとみなされます。弱い検証を作り出す etag のシステムを構築することは、ページのさまざまな要素の重要性を知ることが伴うため複雑になるかもしれませんが、キャッシュの性能を最適化するためにとても役に立ちます。

条件ヘッダー
------

条件ヘッダーと呼ばれるいくつかの HTTP ヘッダーが、条件付きリクエストをもたらします。

`If-Match`

遠方のリソースの `ETag` と、このヘッダーに載せた etag が等しければ成功します。強い検証を行います。

`If-None-Match`

遠方のリソースの `ETag` と、このヘッダーに載せたそれぞれの etag が異なっていれば成功します。弱い検証を行います。

`If-Modified-Since`

遠方のリソースの `Last-Modified` の日時が、このヘッダーで指定した日時より新しければ成功します。

`If-Unmodified-Since`

遠方のリソースの `Last-Modified` の日時が、このヘッダーで指定した日時以前であれば成功します。

`If-Range`

`If-Match` や `If-Unmodified-Since` に似ていますが、 etag または日時をひとつしか持つことができません。条件が失敗すると範囲指定リクエストも失敗して、 `206` `Partial Content` レスポンスの代わりに `200` `OK` でリソース全体を送信します。

使用例
---

### キャッシュの更新

条件付きリクエストのもっとも一般的な使用例は、キャッシュの更新です。キャッシュが空である、あるいはキャッシュを使用しない状態では `200` `OK` ステータスと共に、要求したリソースが送信されます。

![キャッシュが空のときに発行されたリクエストは、 リソースをダウンロードするきっかけとなり、 両方の検証子の値がヘッダーとして送信されます。その後、キャッシュが満たされます。](/ja/docs/Web/HTTP/Conditional_requests/cache1.png)

リソースと共に、ヘッダーで検証子を送信します。この例では `Last-Modified` と `ETag` の両方を送信していますが、どちらか一方しか使用しません。これらの検証子はリソースと共に (すべてのヘッダーのように) キャッシュへ保存され、キャッシュが陳腐化したときに条件付きリクエストを作成するために使用します。

キャッシュが陳腐化していなければ、条件付きリクエストは行いません。しかしキャッシュが陳腐化すると主に `Cache-Control` ヘッダーに制御されて、クライアントはキャッシュされた値を直接使用せず、`If-Modified-Since` または `If-None-Match` ヘッダーに検証子の値を指定した*条件付きリクエスト*を発行します。

リソースが変更されていなければ、サーバーは `304` `Not Modified` レスポンスを返します。これはキャッシュを再び新鮮な状態にして、クライアントはキャッシュされたリソースを使用します。これはリソースをいくらか消費するレスポンスとリクエストのやり取りが発生しますが、通信網でリソース全体を再度転送するよりも効率的です。

![キャッシュが古くなっている状態では、条件付きのリクエストが送信されます。サーバーは、リソースが変更されたかどうかを判断し、このケースのように、同じものであるため再度送信しないことを決定することができます。](/ja/docs/Web/HTTP/Conditional_requests/httpcache2.png)

 リソースが変更された場合、サーバーは新しいバージョンのリソースを含む `200 OK` レスポンスを返します（リクエストが条件付きでなかったかのように）。
 クライアントはこの新しいリソースを使用します（そしてキャッシュします）。

![リソースが変更された場合には、リクエストが条件付きでなかったかのように送り返されます。](/ja/docs/Web/HTTP/Conditional_requests/httpcache3.png)

サーバー側で検証子を設定することをを除いて、この仕組みは透過的です。どのブラウザーもウェブ開発者が特別な作業を行うことなく、キャッシュを管理してこのような条件付きリクエストを送信します。

### 部分ダウンロードの整合性

ファイルの部分ダウンロードは、以前の操作を再開することが可能な HTTP の機能であり、すでに取得済みの情報を保持することによって帯域や時間を節約します。

![ダウンロードが停止し、コンテンツの一部しか取得できていない状態です。](/ja/docs/Web/HTTP/Conditional_requests/httpresume1.png)

部分ダウンロードをサポートするサーバーは、`Accept-Ranges` ヘッダーを送信してそのことを知らせます。このヘッダーが送信されると、クライアントは `Ranges` (en-US) ヘッダーで欠落している範囲を送信することで、ダウンロードを再開できます。

![クライアントは、自分が必要とする範囲を示し、部分的に取得したリクエストの検証子を前提条件としてチェックすることで、リクエストを再開します。](/ja/docs/Web/HTTP/Conditional_requests/httpresume2.png)

この原理はシンプルですが、潜在的な問題がひとつあります。2 回のダウンロードの間にリソースが変更されると、取得した範囲が 2 つの異なるバージョンのリソースに対応してしまい、最終的な文書が壊れてしまうでしょう。

これを防ぐため、条件付きリクエストを使用します。範囲についてこれを行うための方法が 2 つあります。より柔軟な方法は `If-Modified-Since` と `If-Match` を使用することであり、前提条件に合わない場合はサーバーがエラーを返します。すると、クライアントはダウンロードを始めから再実行します。

![部分的にダウンロードされたリソースが変更された場合、前提条件が満たされず、リソースを完全にダウンロードし直さなければなりません。](/ja/docs/Web/HTTP/Conditional_requests/httpresume3.png)

この方法でも動作しますが、文書が変更されると余分なレスポンスやリクエストの交換が発生します。これはパフォーマンスを低下させますので HTTP には、この問題を避けるために特化した追加ヘッダーである `If-Range` があります。

![If-Range ヘッダーを使用すると、リソースが変更されている場合、サーバは直接完全なリソースを送り返すことができ、 412 エラーを送信してクライアントが再度ダウンロードを開始するのを待つ必要がありません。](/ja/docs/Web/HTTP/Conditional_requests/httpresume4.png)

この解決策はより効率的ですが、柔軟性が若干劣ります（条件で etag をひとつしか使用できません）。ただし、これ以上の柔軟性はほとんど必要ありません。

### 楽観的ロックで更新が失われる問題を避ける

リモートの文書の*更新*は、ウェブアプリケーションで一般的な操作です。これはファイルシステムやソース管理アプリケーションではごく一般的ですが、リモートにリソースを保存できるようにするにはこのような仕組みが必要です。同様に、wiki のような一般的なウェブサイトや他の CMS でも必要です。

`PUT` を使用して、この機能を実装できます。クライアントは始めに元のファイルを読み込んで、変更した後にサーバーへ送信します。

![PUT によるファイルの更新は、並行処理ない場合はとても簡単です。](/ja/docs/Web/HTTP/Conditional_requests/httplock1.png)

残念ながら、並行処理を考慮すると若干の間違いが出てきます。あるクライアントがリソースの新たな複製をローカルで変更している間に、第二のクライアントが同じリソースを取得して、クライアント側で同じことを行えます。これにより、とても不幸なことが発生します。両者がリソースを引き渡すと、最初のクライアントが渡した変更点が次に渡されたものによって破棄されて、第二のクライアントは新たな変更点に気づきません。誰が勝ち取ったかの結果は他者には伝わりませんが、どのクライアントの変更点が反映されるかは引き渡す速度によって変わります。またその速度はクライアントやサーバーのパフォーマンス、さらにはクライアント側で人間が文書を編集するパフォーマンスに依存します。勝ち取る者は、その時々で変わります。これは*競合状態*であり、検出やデバッグが難しい不確かな動作をもたらします。

![複数のクライアントが同じリソースを並行して更新していると、競合状態に陥ってしまいます。問題ですね。](/ja/docs/Web/HTTP/Conditional_requests/httplock2.png)

2 つのクライアントの片方を困らせることなく、この問題に対処する方法はありません。しかし、更新が失われたりや競合状態になったりすることは避けるべきです。予測可能な結果や、クライアントが変更点を却下されたときに通知を受けることを望みます。

条件付きリクエストで、*楽観的ロックアルゴリズム* （ほとんどの wiki やソース管理システムで使用されています）を実装できます。この考え方ではすべてのクライアントに、リソースの複製の取得を許可してローカルで変更することを許可します。そして、最初のクライアントが更新内容を送信することを許可して成功させて、以降の古いバージョンになったリソースに基づく更新は拒否します。

![条件付きリクエストにより、楽観的なロックを実装することができます。](/ja/docs/Web/HTTP/Conditional_requests/httplock3.png)

これは `If-Match` および `If-Unmodified-Since` ヘッダーを使用して実装します。etag が元のファイルと一致しない、あるいはファイルが取得したときから変更されている場合は、変更点が `412` `Precondition Failed` エラーで拒否されます。このエラーへの対処はクライアント次第であり、今度は最新のバージョンで再び実行するよう人間に通知する、あるいは *diff* を表示して変更点を維持するかを人間が選択できるように支援します。

### リソースの最初のアップロードに対処する

リソースの最初のアップロードは、前述の状況の特別なケースです。リソースの更新と同様に、2 つのクライアントが同時 (あるいはほぼ同時) にアップロードしようとする競合状態を仮定します。これを防ぐために条件付きリクエストを使用できます。すべての etag を表す特別な値 `'*'` を持つ `If-None-Match` を追加することで、それより前のリクエストが存在しない場合に限り、リクエストが成功します。

![通常のアップロードと同様に、リソースの最初のアップロードには競合状態が発生します。 If-None-Match で防ぐことができます。](/ja/docs/Web/HTTP/Conditional_requests/httpfirst.png)

`If-None-Match` は HTTP/1.1 （およびそれ以降）に準拠するサーバーのみで動作します。サーバーが対応しているかが不明である場合は、始めに確認用の `HEAD` リクエストをリソースに対して発行しなければなりません。

まとめ
---

条件付きリクエストは HTTP の重要な機能であり、効率的で複雑なアプリケーションの構築を可能にします。キャッシュやダウンロードの再開について、ウェブマスターに求められる作業はサーバーを適切に設定することだけです (一部の環境では正しい etag を設定することが難しいかもしれません)。また、ブラウザーが適切な条件付きリクエストを実行しますので、ウェブ開発者に求められる作業はありません

一方、ロックの仕組みでは、ウェブ開発者が適切なヘッダーを伴ってリクエストを発行しなければなりません。ウェブマスターはほとんどの場合、それらの確認をアプリケーションに頼ることができるでしょう。

どちらにせよ、条件付きリクエストはウェブの重要な機能であることは明らかです。


コンテンツセキュリティポリシー (CSP) - HTTP

コンテンツセキュリティポリシー (CSP)
=====================

**コンテンツセキュリティポリシー** (CSP) は、クロスサイトスクリプティング (Cross-site\_scripting) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。
 これらの攻撃はデータの窃取からサイトの改ざん、マルウェアの拡散に至るまで、様々な目的に用いられます。

 CSP は完全な後方互換性を保って設計されています（ただし、 CSP 2 については後方互換性がない点もあり、明示的に記述されています。詳細はこちらの 1.1 章を参照してください）。
 そのため、 CSP に未対応のブラウザーでも CSP 実装済のサーバーと通信でき、逆もまた同様です。 CSP 未対応のブラウザーは単に CSP を無視し、ウェブコンテンツにはこれまで通り標準の同一オリジンポリシーを適用します。
 CSP ヘッダーを送信しないサーバーに対しても、ブラウザーは同様に標準の 同一オリジンポリシー を適用します。

CSP を有効にするには、ウェブサーバーから `Content-Security-Policy` HTTP ヘッダーを返すように設定する必要があります（`X-Content-Security-Policy` ヘッダーに関する記述が時々ありますが、これは古いバージョンのものであり、今日このヘッダーを指定する必要はありません）。

他にも、 `<meta>` 要素を用いてポリシーを指定することも可能です。例を挙げます。

```html
<meta
 http-equiv="Content-Security-Policy"
 content="default-src 'self'; img-src https://\*; child-src 'none';" />
```

脅威
--

### クロスサイトスクリプティングの軽減

 CSP の第一の目的は XSS 攻撃の軽減と報告です。 XSS 攻撃とは、サーバーから取得したコンテンツをブラウザーが信頼する性質を悪用した攻撃です。
 ブラウザーはコンテンツの送信元を信頼するため、たとえ実際の送信元が見かけ上とは異なっていたとしても、悪意あるスクリプトが被害者のブラウザー上で実行されてしまいます。

 サーバー管理者が CSP を利用する場合、ブラウザーが実行可能なスクリプトの有効なソースとみなすドメインを指定することにより、 XSS の発生する箇所を削減・根絶することができます。
 CSP に対応したブラウザーは、サーバーから指定された許可リストに載っているドメインのスクリプトのみ実行し、他のスクリプトはすべて無視します（インラインスクリプトや HTML 属性値のイベントハンドラーも無視する対象に含まれます）。

究極的な防衛策として、スクリプトを決して実行させたくないサイトは、スクリプトの実行を全面的に拒否することも可能です。

### パケット盗聴攻撃の軽減

 取得するコンテンツのドメインを制限することに加えて、サーバーは通信に使うプロトコルを指定することも可能です。
 例えば、（セキュリティの観点からはこれが理想的ですが）すべてのコンテンツを HTTPS で取得されるようにサーバーから指定することが出来ます。
 データ通信におけるセキュリティ戦略を完全なものとするには、HTTPS 通信を強制するだけではなく、すべての Cookie に secure フラグ を付けたり、HTTP ページから対応する HTTPS ページへの自動リダイレクトを整備することも必要です。
 また、ブラウザーが暗号化された通信路のみを用いてサイトに接続することを保証するため、`Strict-Transport-Security` HTTP ヘッダーを利用することも可能です。

CSP の適用
-------

 コンテンツセキュリティポリシーを適用するには、該当するウェブページに `Content-Security-Policy` HTTP ヘッダーを返すようにし、ユーザエージェントが読み込むことのできるリソースの情報を指定します。
 例えば、画像のアップロードや表示を行うページの場合、画像の出元は任意の場所で構いませんが、フォームの action 属性値は特定のエンドポイントに制限する必要があります。
 コンテンツセキュリティポリシーを適切に設計すれば、クロスサイトスクリプティング攻撃に対する耐性を高めることができます。
 この記事では、適切なヘッダーの作成方法と記述例を紹介します。

### ポリシーの設定

ポリシーの設定には `Content-Security-Policy` HTTP ヘッダーを以下のように用います。

```http
Content-Security-Policy: policy
```

`policy` の箇所には、適用したいコンテンツセキュリティポリシーを表すディレクティブから構成される文字列が入ります。

### ポリシーの記述

 ポリシーはポリシーディレクティブを列挙することで表現します。このポリシーディレクティブは、特定の種類のリソースや、ポリシーの適用範囲をそれぞれ表すものです。
 ポリシーには `default-src` ディレクティブを指定するべきでしょう。このディレクティブは、ポリシーについて特に指定のないリソースに対するフォールバックの役目を果たします（一覧については `default-src` の説明を参照してください）。
 また、インラインスクリプトや `eval()` の実行を防ぐには `default-src` や `script-src` を指定する必要があります。
 さらに、`<style>` 要素や `style` 属性によるインラインスタイルの適用を防ぐには `default-src` や `style-src` の指定が必要となります。
 さまざまな種別のアイテムに対して特定のディレクティブが存在します。フォント、フレーム、画像、音声・動画、スクリプト、ワーカーなど、各々の種別に固有のポリシーを持たせることができます。

ポリシーディレクティブの一覧については Content-Security-Policy ヘッダーを参照してください。

一般的な適用例
-------

この章では、一般的なセキュリティポリシーの適用例を示します。

### 例 1

サイト管理者が、すべてのコンテンツをサイト自身のドメイン（サブドメインを除く）から取得させたい場合。

```http
Content-Security-Policy: default-src 'self'
```

### 例 2

サイト管理者が、信頼されたドメインとそのすべてのサブドメインからのコンテンツを許可したい場合（CSPがセットされたドメインと同一とは限らない）。

```http
Content-Security-Policy: default-src 'self' example.com \*.example.com
```

### 例 3

サイト管理者がウェブアプリのユーザーに、任意のドメインからの画像読み込みを許可したい場合。ただし、音声や動画は信頼された配信元からのものだけに制限し、すべてのスクリプトは、信頼されたコードをホストする特定のサーバーのみに制限する。

```http
Content-Security-Policy: default-src 'self'; img-src \*; media-src example.org example.net; script-src userscripts.example.com
```

この例では、コンテンツのデフォルト設定としてドキュメント自身のホストのみを許可していますが、以下の例外を認めています。

* 画像は任意の場所から読み込まれます（ワイルドカード "\*" による指定に注意）。
* メディアは example.org と example.net のものだけが許可されます（ただしサブドメインは許可されません）。
* 実行可能なスクリプトは userscripts.example.com のものだけ許可されます。
### 例 4

サイト管理者がオンラインバンキングのウェブサイトについて、リクエスト時の盗聴攻撃を防ぐため、すべてのコンテンツを TLS で読み込むようにしたい場合。

```http
Content-Security-Policy: default-src https://onlinebanking.example.com
```

この例では、ドメインを単一オリジン onlinebanking.example.com のみに制限し、かつドキュメントへのアクセスを HTTPS のみに制限しています。

### 例 5

サイト管理者がウェブメールサイトについて、メール内の HTML を許可し、任意のドメインから画像の読み込みを許可するが、JavaScript や他に危険性のあるコンテンツは許可したくない場合。

```http
Content-Security-Policy: default-src 'self' \*.example.com; img-src \*
```

この例では、 `script-src` を指定していないことに注意してください。この CSP を適用したサイトは、スクリプトに関して `default-src` ディレクティブの設定を適用します。つまり、スクリプトは元のサーバーのものだけ読み込まれます。

ポリシーのテスト
--------

本番環境への適用をスムーズに行うため、CSP は report-only モードで動作させることが可能です。このモードの場合、ポリシーによるブロックは行われず、指定した URI へポリシー違反の内容が報告されます。また、新しいポリシーを本番環境に適用する前に試験運用する際にも report-only モードは利用できます。

ポリシーを report-only モードで動作させるには、以下のようにポリシーを `Content-Security-Policy-Report-Only` HTTP ヘッダーに指定します。

```http
Content-Security-Policy-Report-Only: policy
```

 同じレスポンス中に `Content-Security-Policy-Report-Only` ヘッダーと `Content-Security-Policy` ヘッダーが存在した場合、どちらのポリシーも考慮されます。
 `Content-Security-Policy` ヘッダーに指定したポリシーについてはブロックが行われ、`Content-Security-Policy-Report-Only` ヘッダーに指定したポリシーは報告のみが行われます。

報告機能の利用
-------

既定では、違反内容は報告されません。違反内容の報告機能を有効にするには `report-uri` ポリシーディレクティブを指定し、報告先の URI を 1 つ以上指定する必要があります。

```http
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
```

URI を指定したら報告を受け取るサーバーを立ち上げます。受信した内容は適切に感じるどんな方法でも保存・処理することができます。

違反内容の報告の構文
----------

違反内容は以下のデータを含んだ JSON オブジェクトで送信されます。

`blocked-uri`

 コンテンツセキュリティポリシーによって読み込みがブロックされたリソースの URI。
 ブロックされた URI が `document-uri` とは異なるオリジンだった場合、ブロックされた URI はスキーム・ホスト・ポートのみを含むように切り詰められます。

`disposition`

`"enforce"` または `"report"` のいずれかで、 `Content-Security-Policy-Report-Only` ヘッダーか `Content-Security-Policy` ヘッダーのどちらが使われているかで決まります。

`document-uri`

違反が生じた文書の URI。

`effective-directive`

 実行により違反を起こしたディレクティブ。
 ブラウザーによっては異なる値を提供します。例えば Chrome の場合は実際に違反が発生したディレクティブが `style-src` でも `style-src-elem`/`style-src-attr` を提供します。

`original-policy`

`Content-Security-Policy` HTTP ヘッダーに元々指定されていたポリシー。

`referrer`
非推奨

Non-standard

違反が生じた文書のリファラー。

`script-sample`

違反を起こしたインラインスクリプト、イベントハンドラー、スタイルの最初の 40 文字。 `'report-sample'` が含まれている場合に `script-src*` と `style-src*` のみに適用されます。

`status-code`

グローバルオブジェクトが初期化されたリソースの HTTP ステータスコード。

`violated-directive`

違反したポリシーセクションの名前。

違反報告の例
------

`http://example.com/signup.html` というページを例に考えます。ここでは次のようなポリシーを指定しており、 `cdn.example.com` のスタイルシートのみを許可しています。

```http
Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /\_/csp-reports
```

`signup.html` の内容は次の通りです。

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    Here be content.
  </body>
</html>
```

間違いがあることにお気付きでしょうか？スタイルシートの読み込みは `cdn.example.com` からのみに制限されていますが、実際には自身のドメイン (`http://example.com`) から読み込もうとしています。このドキュメントを閲覧した際には、次のような違反内容が `http://example.com/_/csp-reports` へ POST リクエストで送信されます。

```json
{
  "csp-report": {
    "document-uri": "http://example.com/signup.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /\_/csp-reports"
  }
}
```

 ご覧の通り、`blocked-uri` には違反の原因となったリソースのフルパスが記録されています。
 ただし、必ずフルパスが記録されるとは限りません。
 例えば、 `signup.html` が `http://anothercdn.example.com/stylesheet.css` から CSS を読み込もうとした場合、`blocked-uri` にはフルパスではなくオリジンのみ (`http://anothercdn.example.com`) が記録されます。
 この一見不思議な挙動は CSP の仕様書に 説明されています。
 手短に言うと、この挙動はクロスオリジンのリソースに関する機密情報の漏えいを防ぐために規定されています。

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### 互換性のメモ

一部のバージョンの Safari には、コンテンツセキュリティポリシーヘッダーが設定されていて Same Origin ヘッダーがないと、ブラウザーが自分自身でホストされたコンテンツやオフサイトコンテンツをブロックし、コンテンツセキュリティポリシーがそのコンテンツを許可していないという誤った報告をするという顕著な非互換があります。

関連情報
----

* HTTP の `Content-Security-Policy` ヘッダー
* HTTP の `Content-Security-Policy-Report-Only` ヘッダー
* WebExtensions のコンテンツセキュリティ
* ウェブワーカーでの CSP
* プライバシー、許可、情報セキュリティ
* CSP Evaluator - Evaluate your Content Security Policy


HTTP レスポンスステータスコード - HTTP

HTTP レスポンスステータスコード
==================

 HTTP のレスポンスステータスコードは、特定の HTTP リクエストが正常に完了したどうかを示します。
 レスポンスは 5 つのクラスに分類されています。

1. 情報レスポンス (`100`–`199`)
2. 成功レスポンス (`200`–`299`)
3. リダイレクトメッセージ (`300`–`399`)
4. クライアントエラーレスポンス (`400`–`499`)
5. サーバーエラーレスポンス (`500`–`599`)

以下のステータスコードは RFC 2616 の第 10 章で定義されています。更新版の仕様書は RFC 7231 にあります。

**メモ:** この一覧にないレスポンスを受け取った場合、それは標準外のレスポンスであり、おそらくそのサーバーソフトウェアに固有のものです。

情報レスポンス
-------

`100 Continue`

これは暫定レスポンスで、その時点までのすべてに問題がなく、クライアントはリクエストを継続してよい、またもしリクエストが完了している場合はレスポンスを無視してよいことを示します。

`101 Switching Protocols`

このコードはクライアントからの `Upgrade` リクエストヘッダーのレスポンスとして送信され、サーバーはプロトコルを切り替えていることを示します。

`102 Processing` (WebDAV)

このコードは、サーバーはリクエストを受け取って処理しているが、まだレスポンスを提供できないことを示します。

`103 Early Hints`

このステータスコードは主に `Link` ヘッダーとともに使用され、サーバーがリソースを準備している間、ユーザーエージェントがリソースの先読みを開始できるようにするためのものです。

成功レスポンス
-------

`200 OK`

リクエストが成功したことを示します。成功が意味することは、 HTTP メソッドにより異なります。

* `GET`: リソースが読み込まれ、メッセージ本文で転送された。
* `HEAD`: メッセージ本文がなく、表現ヘッダーがレスポンスに含まれている。
* `PUT` または `POST`: 操作の結果を表すリソースがメッセージ本文で送信される。
* `TRACE`: メッセージ本文に、サーバーが受け取ったリクエストメッセージが含まれている。

`201 Created`

リクエストは成功し、その結果新たなリソースが作成されたことを示します。これは一般的に、 `POST` リクエストや、一部の `PUT` リクエストを送信した後のレスポンスになります。

`202 Accepted`

 リクエストは受理されたが、まだ実行されていないことを示します。
 これはあいまいです。 HTTP ではリクエストを処理した結果を示す非同期なレスポンスを後から送信する方法がないためです。
 リクエストは別のプロセスかサーバーが処理する、またはバッチ処理する予定です。

`203 Non-Authoritative Information`

 このレスポンスコードは、返されるメタ情報のセットが生成元のサーバーから得られるセットと同一ではなく、ローカルまたは第三者の持つ複製から収集したことを表します。
 これは主に、他のリソースのミラーやバックアップを使用したときに使用されます。
 このような場合以外は、このステータスより `200 OK` のほうが好ましいレスポンスです。

`204 No Content`

リクエストに対して送信するコンテンツはありませんが、ヘッダーは有用であることを示します。ユーザーエージェントはこのリソースに関するキャッシュ済みのヘッダーを、新たな内容に更新します。

`205 Reset Content`

ユーザーエージェントに対し、リクエストを送信した文書をリセットするよう伝達します。

`206 Partial Content`

このレスポンスコードは、クライアントが `Range` ヘッダーを送信し、リソースの一部だけをリクエストした時に使用されます。

`207 Multi-Status` (WebDAV)

複数のステータスコードがあてはまる状況で、複数のリソースに関する情報を伝えます。

`208 Already Reported` (WebDAV)

同じコレクションに繰り返し複数のバインディングする内部メンバーを列挙することを避けるため、 `<dav:propstat>` レスポンス要素の内部で使用します。

`226 IM Used` (HTTP Delta encoding)

サーバーはリソースへの `GET` リクエストの処理を完了しており、レスポンスは現在のインスタンスに適用された 1 つ以上の instance manipulation の結果を表します。

リダイレクトメッセージ
-----------

`300 Multiple Choice`

リクエストに対して複数のレスポンスがあることを示します。ユーザーエージェントやユーザーは、それらからひとつを選択します。 (複数のレスポンスからひとつを選ぶ方法は標準化されていませんが、選択肢へリンクする HTML が推奨されており、それによってユーザーが選択することができます。)

`301 Moved Permanently`

リクエストされたリソースの URL が永遠に変更されたことを示します。レスポンスで新しい URL が与えられます。

`302 Found`

 このレスポンスコードは、リクエストされたリソースの URI が *一時的に* 変更されたことを示します。
 URI は将来、さらに変更される可能性があります。従って、クライアントは将来のリクエストでも同じ URI を使用するべきです。

`303 See Other`

サーバーはこのレスポンスを、リクエストされたリソースを別の URI で GET リクエストを使用して取得するようクライアントを誘導するために送信します。

`304 Not Modified`

 これはキャッシュ用に使用します。
 このレスポンスコードはクライアントに対して、レスポンスは変更されていないことを示します。よって、クライアントはキャッシュ済みのレスポンスを使い続けます。

`305 Use Proxy`
非推奨

 これは旧バージョンの HTTP 仕様書で、リクエストされたレスポンスはプロキシーからアクセスしなければならないことを示していました。
 プロキシーのインバンド設定に関するセキュリティの懸念により、このレスポンスコードは非推奨になりました。

`306 unused`

このレスポンスコードはもう使用されず、予約済みです。 HTTP/1.1 仕様書の旧バージョンでは使用されていました。

`307 Temporary Redirect`

 サーバーはこのレスポンスを、リクエストされたリソースを別の URI で、元のリクエストと同じメソッドを使用して取得するようクライアントを誘導するために送信します。
 これは `302 Found` HTTP レスポンスコードと同じ意味を持ちますが、ユーザーエージェントは使用する HTTP メソッドを*変更してはならない*点が異なります。始めのリクエストで `POST` を用いた場合は、次のリクエストでも `POST` を使用しなければなりません。

`308 Permanent Redirect`

 これは、リソースが HTTP の `Location:` レスポンスヘッダーで指定した別の URI へ永続的に置かれていることを示します。
 これは `301 Moved Permanently` HTTP レスポンスコードと同じ意味を持ちますが、ユーザーエージェントは使用する HTTP メソッドを*変更してはならない*点が異なります。始めのリクエストで `POST` を用いた場合は、次のリクエストでも `POST` を使用しなければなりません。

クライアントエラーレスポンス
--------------

`400 Bad Request`

構文が無効であるためサーバーがリクエストを理解できないことを示します。

`401 Unauthorized`

 HTTP 標準では "unauthorized" (不許可) と定義されていますが、意味的にはこのレスポンスは "unauthenticated" (未認証) です。
 つまり、クライアントはリクエストされたレスポンスを得るためには認証を受けなければなりません。

`402 Payment Required`
Experimental

このレスポンスコードは、将来のために予約されています。このコードは当初、デジタル決済システムで使用するために作成されましたが、ごく稀にしか使用されておらず、標準的な慣例はありません。

`403 Forbidden`

 認証されていないなどの理由でクライアントにコンテンツのアクセス権がなく、サーバーが適切なレスポンスの返信を拒否していることを示します。
 `401 Unauthorized` とは異なり、クライアントの ID がサーバーに知られています。

`404 Not Found`

 サーバーがリクエストされたリソースを発見できないことを示します。
 ブラウザーでは、これは URL が解釈できなかったことを意味します。
 API では、これは通信先が有効であるものの、リソース自体が存在しないことを意味することがあります。
 サーバーは認証されていないクライアントからリソースの存在を隠すために、 403 の代わりにこのレスポンスを返すことがあります。
 このレスポンスコードはウェブで頻繁に見られるため、おそらくもっとも有名なコードでしょう。

`405 Method Not Allowed`

サーバーがリクエストメソッドを理解しているものの、無効にされており使用することができません。例えば、 API がリソースを DELETE することを禁止できます。 `GET` および `HEAD` の 2 つは必須で、無効にすることができず、このエラーコードを返してはいけません。

`406 Not Acceptable`

このレスポンスは、ウェブサーバーが サーバー駆動型コンテンツネゴシエーション (en-US) を行った結果、ユーザーエージェントから与えられた条件に合うコンテンツが見つからない場合に送信されます。

`407 Proxy Authentication Required`

これは `401 Unauthorized` と似ていますが、プロキシーサーバーが認証を要求している点が異なります。

`408 Request Timeout`

 このレスポンスはクライアントが以前にリクエストを行っていない、アイドル状態の接続において一部のサーバーが送信します。
 サーバーが使用していない接続の終了を望んでいることを示します。
 このレスポンスは Chrome、 Firefox 27 以降、IE9 など、閲覧を高速化するための HTTP 事前接続機能を使用する一部のブラウザーでよく使用します。
 また、一部のサーバーはこのメッセージを送らずに接続を閉じることに注意してください。

`409 Conflict`

このレスポンスは、リクエストがサーバーの現在の状態と矛盾する場合に送られるでしょう。

`410 Gone`

 このレスポンスは、リクエストされたコンテンツがサーバーから永久に削除され、転送先アドレスがない場合に送られます。
 クライアントはこのリソースへのキャッシュやリンクを削除することが期待されます。
 HTTP 仕様書ではこのコードを「期間限定のプロモーションサービス」に使用することを意図しています。
 API はこのステータスコードの場合、削除されたリソースを無理に示そうとするべきではありません。

`411 Length Required`

サーバーが `Content-Length` ヘッダーフィールドを要求しているが、リクエストで定義されていないために、サーバーがリクエストを拒否したことを示します。

`412 Precondition Failed`

サーバー側で適合しない前提条件が、クライアント側のヘッダーに含まれていることを示します。

`413 Payload Too Large`

 リクエストの本体がサーバーで定めている上限を超えていることを示します。
 サーバーは接続を閉じるか、`Retry-After` ヘッダーフィールドを返します。

`414 URI Too Long`

クライアントがリクエストした URI が、サーバーで扱える長さを超えていることを示します。

`415 Unsupported Media Type`

リクエストされたデータのメディア形式をサーバーが対応しておらず、サーバーはリクエストを拒否したことを示します。

`416 Range Not Satisfiable`

 リクエスト内の `Range` ヘッダーフィールドで指定された範囲を満たすことができないことを示します。
 指定した範囲が、目的の URI のデータサイズを超えている可能性があります。

`417 Expectation Failed`

このレスポンスコードは、`Expect` リクエストヘッダーで指定された内容がサーバー側と適合しないことを示します。

`418 I'm a teapot`

サーバーは、ティーポットでコーヒーを淹れようとする試みを拒否します。

`421 Misdirected Request`

 リクエストは、レスポンスを生成できないサーバーに送られました。
 リクエストの URI に含まれているスキームや権限の組み合わせに対してレスポンスを生成するよう設定されていないサーバーが、このコードを送ることがあります。

`422 Unprocessable Entity` (WebDAV)

リクエストは適正ですが、意味が誤っているために従うことができません。

`423 Locked` (WebDAV)

アクセス中のリソースはロックされています。

`424 Failed Dependency` (WebDAV)

前のリクエストが失敗したため、このリクエストも失敗しました。

`425 Too Early`
Experimental

サーバーが、繰り返される可能性のあるリクエストを処理するリスクを望まないことを示します。

`426 Upgrade Required`

 サーバーは現在のプロトコルを使用したリクエストの実行を拒否しましたが、クライアントが別のプロトコルにアップグレードした後は受け入れることができます。
 サーバーは必要なプロトコルを示すために、426 のレスポンスで `Upgrade` ヘッダーフィールドを送信しなければなりません。

`428 Precondition Required`

 オリジンサーバーはリクエストが条件付きになることを必要としています。
 このレスポンスは「ロストアップデート問題」 (クライアントがリソースの状態を取得して変更およびサーバーに送信している間に、第三者がサーバーの状態を変更して競合が発生すること) を防ごうとするものです。

`429 Too Many Requests`

ユーザーは一定の時間内に大量のリクエストを送信しました ("レート制限")。

`431 Request Header Fields Too Large`

 ヘッダーフィールドが大きすぎるため、サーバーはリクエストの処理を望みません。
 ヘッダーフィールドのサイズを削減した後に、リクエストを再送信できます。

`451 Unavailable For Legal Reasons`

ユーザーエージェントが政府によって検閲されたウェブページなど、違法なリソースをリクエストしています。

サーバーエラーレスポンス
------------

`500 Internal Server Error`

サーバー側で処理方法がわからない事態が発生したことを示します。

`501 Not Implemented`

リクエストメソッドをサーバーが対応しておらず、扱えないことを示します。サーバーが対応しなければならない (従って、このコードを返してはならない) メソッドは `GET` と `HEAD` だけです。

`502 Bad Gateway`

このエラーレスポンスは、リクエストの処理に必要なレスポンスを受け取るゲートウェイとして動作するサーバーが無効なレスポンスを受け取ったことを示します。

`503 Service Unavailable`

 サーバーはリクエストを処理する準備ができていないことを示します。
 一般的な原因は、サーバーがメンテナンスや過負荷でダウンしていることです。
 このレスポンスとともに問題について説明する、ユーザーにわかりやすいページを送信するべきであることに注意してください。
 このレスポンスは一時的な状況について使用するものであり、また可能であれば、サービスが復旧する前に HTTP の `Retry-After` ヘッダーに予定時刻を含めてください。
 また、これら一時的な状況のレスポンスは通常キャッシュされるべきではないことから、ウェブ管理者はこのレスポンスとともに送られるキャッシュ関連のヘッダーに注意しなければなりません。

`504 Gateway Timeout`

このエラーレスポンスは、ゲートウェイとして動作するサーバーが時間内にレスポンスを得られない場合に送られます。

`505 HTTP Version Not Supported`

リクエストで使用した HTTP のバージョンにサーバーが対応していないことを示します。

`506 Variant Also Negotiates`

サーバーに内部構成エラーがあることを示します。選択したバリアントリソースが透過的コンテンツネゴシエーション自体に携わるよう設定されており、ネゴシエーションプロセスが正しく終了しなかったことを示します。

`507 Insufficient Storage` (WebDAV)

サーバーがリクエストを完了させるのに必要な表現を保存することができなかったため、メソッドがリソースに対して実行できなかったことを示します。

`508 Loop Detected` (WebDAV)

サーバーは、リクエストの処理中に無限ループを検出しました。

`510 Not Extended`

サーバーがリクエストを処理するために、リクエストをさらに拡張することが必要です。

`511 Network Authentication Required`

クライアントがネットワークでアクセスするために認証が必要であることを示します。

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Wikipedia の、HTTP ステータスコードの一覧
* HTTP ステータスコードの、IANA 公式レジストリー


HTTP 認証 - HTTP

HTTP 認証
=======

 HTTP はアクセス制御と認証の基本的な枠組みを提供しています。
 このページでは、 HTTP の認証の枠組みを紹介し、サーバーで HTTP の "Basic" 認証を使用してアクセスを制限する方法を紹介します。

一般的な HTTP 認証の枠組み
----------------

RFC 7235 は、サーバーがクライアントのリクエストをチャレンジし、クライアントが認証情報を提供するために使用できる HTTP 認証フレームワークを定義しています。

チャレンジとレスポンスの流れは以下のようになります。

1. サーバーは少なくとも 1 回のチャレンジで、クライアントに `401` (Unauthorized) レスポンスステータスを返し、 `WWW-Authenticate` レスポンスヘッダーを含めて認証方法に関する情報を提供します。
2. そのサーバーで自身を認証したいクライアントは、 `Authorization` リクエストヘッダーフィールドに資格情報を含めることでそれを行うことができます。
3. 通常、クライアントはユーザーにパスワードのプロンプトを表示し、正しい `Authorization` ヘッダーを含むリクエストを発行します。

![クライアントとサーバーのライフライン間の HTTP メッセージを説明するシーケンス図。](/ja/docs/Web/HTTP/Authentication/http-auth-sequence-diagram.png)

 上記の全体的なメッセージの流れは、（すべてではありませんが）多くの認証方式で同じです。
 ヘッダーに含まれる実際の情報とそのエンコード方法は変わります。

**警告:** 上記の図で使用されている "Basic" 認証方式は、資格情報をエンコードしますが暗号化はしません。
 これは安全な接続 (HTTPS/TLS) を介して行わなければ完全に安全ではありません。

### プロキシー認証

*プロキシー認証*にも同じチャレンジとレスポンスのメカニズムを使用することができます。
 リソース認証とプロキシー認証の両方が共存できるように、別なヘッダーとステータスコードのセットが必要です。プロキシーの場合、チャレンジのステータスコードは `407` (Proxy Authentication Required) であり、 `Proxy-Authenticate` レスポンスヘッダーにプロキシーで受け付けるためのチャレンジを 1 つ以上設定します。プロキシーサーバーに資格情報を伝えるには、 `Proxy-Authorization` リクエストヘッダーが使用されます。

### アクセスの不許可

（プロキシー）サーバーが*無効な*資格情報を受け取った場合、 `401` `Unauthorized` または `407` `Proxy Authentication Required` で応答する必要があり、ユーザーは新しいリクエストを送ったり、 `Authorization` ヘッダーフィールドを置き換えたりすることができます。

（プロキシー）サーバーが、有効であるが指定されたリソースにアクセスする要件を満たさない資格情報を受け取った場合、サーバーは `403` `Forbidden` ステータスコードを返す必要があります。 `401` `Unauthorized` または `407` `Proxy Authentication Required` とは異なり、このユーザーとブラウザーは再試行することができません。

どの場合でも、サーバーは `404` `Not Found` ステータスコードを返すことで、十分な権限がない、または正しく認証されていないユーザーからページの存在を隠すことができます。

### オリジン間の画像の認証

 （ブラウザーで修正された）潜在的なセキュリティホールとして、サイトをまたいだ画像の認証があります。
 Firefox 59 以降、異なるオリジンから現在の文書に読み込まれる画像リソースは、 HTTP 認証ダイアログを起動することができなくなり (Firefox バグ 1423146)、攻撃者が任意の画像をサードパーティ製のページに埋め込んでユーザーの認証情報を盗むことを防ぎます。

### HTTP 認証の文字エンコーディング

ブラウザーはユーザー名とパスワードに `utf-8` エンコーディングを使用します。

Firefox は `ISO-8859-1` を使用していましたが、他のブラウザーとの互換性のために `utf-8` に変更され、 Firefox バグ 1419658 で説明されているような潜在的な問題を回避します。

### WWW-Authenticate および Proxy-Authenticate ヘッダー

`WWW-Authenticate` および `Proxy-Authenticate` レスポンスヘッダーは、リソースへのアクセスに使用する認証メソッドを定義します。どの認証方式を使用するかを指定するため、認証を希望するクライアントは資格情報の提供方法を知ることができます。

これらのヘッダーの構文は以下の通りです。

```http
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
```

ここで、 `<type>` は認証方式です ("Basic" は最も一般的な方式であり、以下で紹介します)。 *realm* は保護された領域を説明するため、または保護の範囲を示すために使用されます。これは、「ステージングサイトへのアクセス」などのようなメッセージにすることができ、それによってユーザーが、どの領域にアクセスしようとしているかを知ることができます。

### Authorization および Proxy-Authorization ヘッダー

`Authorization` および `Proxy-Authorization` リクエストヘッダーには、（プロキシー）サーバーがユーザーエージェントを認証する資格情報が入ります。ここでは、 `<type>` が再び必要となり、その後に使用される認証方式によって符号化または暗号化された資格情報が続きます。

```http
Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>
```

認証方式
----

一般的な HTTP 認証フレームワークは、いくつかの認証方式によって使用されます。方式はセキュリティ強度とクライアント、またはサーバーソフトウェアでの可用性が異なる場合があります。

IANA は認証方式の一覧を管理していますが、 Amazon AWS などのホストサービスが提供する他の方式もあります。一般的な認証方式には次のものがあります。

よく使われる認証方式には次のようなものがあります。

**Basic**

RFC 7617 を参照。 base64 でエンコードされた資格情報です。詳しくは後述します。

**Bearer**

RFC 6750 を参照。 OAuth 2.0 で保護されたリソースにアクセスするベアラートークンです。

**Digest**

RFC 7616 を参照。 Firefox 93 以降は SHA-256 アルゴリズムに対応しています。以前のバージョンでは MD5 ハッシュだけに対応していまました（非推奨）。

**HOBA**

RFC 7486 3 章を参照、 HTTP オリジン認証 (**H**TTP **O**rigin-**B**ound **A**uthentication)、電子署名ベース

**Mutual**

RFC 8120 を参照

**Negotiate** / **NTLM**

RFC4599 を参照

**VAPID**

RFC 8292 を参照

**SCRAM**

RFC 7804 を参照

**AWS4-HMAC-SHA256**

AWS docs を参照。この方式は AWS3 サーバー認証に使用されています。

方式は、セキュリティの強さや、クライアントまたはサーバーソフトウェアで利用可能かどうかが異なります。

 "Basic" 認証方式はセキュリティが非常に弱いのですが、広く対応されており、セットアップが簡単です。
 以下で詳しく説明します。

Basic 認証方式
----------

"Basic" HTTP 認証方式は RFC 7617 で定義されており、資格情報を送信するのに、ユーザー ID とパスワードの組を base64 を使用してエンコードします。

### Basic 認証の安全性

ユーザー ID とパスワードは、ネットワークを介してクリアテキストとして渡されるため（base64 でエンコードされますが、 base64 は可逆エンコードです）、 Basic 認証方式は**安全ではありません**。 Basic 認証と組み合わせて HTTPS/TLS を使用する必要があります。これらの追加のセキュリティ強化機能がない場合は、機密情報や重要な情報を保護するために Basic 認証を使用しないでください。

### Apache と Basic 認証によるアクセス制限

Apache サーバー上のディレクトリをパスワードで保護するには、 `.htaccess` ファイルと `.htpasswd` ファイルが必要です。

`.htaccess` ファイルは通常、次のようになります。

```apacheconf
AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user
```

`.htaccess` ファイルは `.htpasswd` ファイルを参照しており、このファイルの各行にはユーザー名とパスワードをコロン (`:`) で区切って記述されています。実際のパスワードは（この場合は MD5 ベースのハッシュを使用して）ハッシュ化されているので表示できません。なお、必要に応じて `.htpasswd` ファイルの名前を変更することができますが、このファイルには誰にもアクセスできないようにしてください。（Apache は通常 `.ht*` ファイルへのアクセスを禁止するように構成されています）。

```apacheconf
aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/
```

### nginx と Basic 認証によるアクセス制限

nginx の場合は、保護する場所とパスワードで保護された領域に名前を指定する `auth_basic` ディレクティブを指定する必要があります。`auth_basic_user_file` ディレクティブは上の Apache の例のように、暗号化されたユーザー資格情報を含む `.htpasswd` ファイルを指します。

```apacheconf
location /status {
    auth_basic           "Access to the staging site";
    auth_basic_user_file /etc/apache2/.htpasswd;
}
```

### URL 内の認証情報を使用したアクセス

多くのクライアントでは次のように、ユーザー名とパスワードを含むエンコードされた URL を使用してログインプロンプトを回避できます。
```

https://username:password@www.example.com/
```

**これらの URL の使用は推奨されていません。**
 Chrome ではセキュリティ上の理由から、URL の `username:password@` 部分が削除されます。 Firefox ではサイトが実際に認証を要求するかどうかをチェックし、そうでない場合 Firefox はユーザーに「`www.example.com` というサイトに `username` というユーザー名でログインしようとしていますが、このウェブサイトは認証を必要としません。これはあなたを騙そうとしている可能性があります。」と警告します。

関連情報
----

* `WWW-Authenticate`
* `Authorization`
* `Proxy-Authorization`
* `Proxy-Authenticate`
* `401`, `403`, `407`


HTTP の概要 - HTTP

HTTP の概要
========

**HTTP** は、 HTML 文書などのリソースを読み取るためのプロトコルです。
 これはウェブにおけるデータ交換の基礎をなし、クライアントサーバープロトコルであり、リクエストは受け取り者（一般にはウェブブラウザー）が生成します。
 文書全体は、テキスト、レイアウトの定義、画像、動画、スクリプトなど、取り込まれたさまざまなサブ文書から再構成されます。

![ウェブの文書は複数のリソースの組み合わせ](/ja/docs/Web/HTTP/Overview/fetching_a_page.png)

 クライアントとサーバーは、（データの流れとは対照的に）個々のメッセージを交換することによって通信します。
 クライアント（通常はウェブブラウザー）が送信するメッセージは*リクエスト*と呼ばれます。また、サーバーが回答として送信するメッセージは*レスポンス*と呼ばれます。

![HTTP はアプリケーション層のプロトコルであり、 TCP （トランスポート層）や IP （ネットワーク層）やプレゼンテーション層以下の上の階層に当たります。](/ja/docs/Web/HTTP/Overview/http-layers.png)1990 年代初頭に設計された HTTP は、時間をかけて進化した拡張可能なプロトコルです。
 HTTP は、 TCP または TLS （暗号化された TCP 接続）を使用して送信されるアプリケーション層のプロトコルですが、理論上は信頼性のある任意のトランスポート層プロトコルを使用できます。
 HTTP は拡張性があるため、ハイパーテキスト文書だけでなく画像や動画の取り込みや、 HTML フォームの入力結果などをクライアントからサーバーへ送信することもできます。
 また、リクエストに応じてウェブページを更新するために、文書の一部を取り込むこともできます。

HTTP ベースシステムの構成要素
-----------------

 HTTP はクライアントサーバープロトコルであり、リクエストはユーザーエージェント（または代理のプロキシー）というひとつの実体から送信されます。
 ほとんどの場合、ユーザーエージェントはウェブブラウザーですが、例えば検索エンジンのインデックスを収集および保守するためにウェブをクロールするロボットなど、どれでもクライアントになることができます。

 個々のリクエストはサーバーに送信され、処理した後に*レスポンス*と呼ばれる回答を提供します。
 クライアントとサーバーとの間には、例えばゲートウェイやキャッシュなどの様々な操作を行う、まとめてプロキシーサーバーと呼ばれるいくつもの実体が存在しています。

![クライアントとサーバーの連鎖](/ja/docs/Web/HTTP/Overview/client-server-chain.png)

 実際はブラウザーとサーバーの間に、ルーターやモデムなどリクエストを扱うコンピューターがさらに存在します。
 ウェブが階層構造で設計されたおかげで、これらはネットワークやトランスポート層の中に隠されています。
 HTTP はアプリケーション層の最上位に存在します。
 ネットワークの問題を診断することは重要ですが、 HTTP を説明する際に下層のことはほとんど重要ではありません。

### クライアント: ユーザーエージェント

*ユーザーエージェント*は、ユーザのために働くツールです。
 この役割は主に、ウェブブラウザーが担いますが、エンジニアやウェブ開発者がアプリケーションをデバッグするために使用するプログラムである可能性もあります。

 ブラウザーは**常に**、リクエストを生成する実体です。
 サーバーにはなりません（もっとも、サーバーが生成するメッセージをシミュレートする仕組みが近年追加されましたが）。

 ウェブページを表示するため、ブラウザーはページを表す HTML 文書を読み込むための最初のリクエストを送信します。
 このファイルを解析して、実行するスクリプト、表示するレイアウトの情報 (CSS)、ページに含まれるサブリソース（通常、画像や動画）に対応する追加のリクエストを発行します。
 そして、ウェブブラウザーはこれらのリソースを組み合わせて、完全な文書であるウェブページを提供します。
 ブラウザーによって実行されるスクリプトが後の段階でさらにリソースを取り込んで、それに応じてブラウザーがウェブページを更新することがあります。

 ウェブページは、ハイパーテキスト文書です。
 これは表示されているコンテンツの一部が新たなウェブページの取り込みを（通常、マウスのクリックによって）発生させるリンクであり、ユーザーがユーザーエージェントを導いてウェブ内を移動できるということです。
 ブラウザーはこれらの導きを HTTP リクエストに変換して、さらにユーザーへ明確なレスポンスを返すために HTTP レスポンスを解釈します。

### ウェブサーバー

 通信路の反対側は、クライアントのリクエストに応じて文書を*提供する*サーバーがいます。
 サーバーは、仮想的には 1 台だけのマシンとしてしか見えませんが、実際には負荷を分担する（ロードバランシング）サーバーの集合であったり、他にも（キャッシュ、データベースサーバー、電子商取引サーバーなど）、要求に応じて文書を全体的または部分的に生成するソフトウェアであったりします。

 サーバーは 1 台のマシンである必要性はありませんが、複数のサーバーのソフトウェアインスタンスを同じマシンで運用することができます。
 HTTP/1.1 と `Host` ヘッダーによって、同じ IP アドレスを共有できます。

### プロキシー

 ウェブブラウザーとウェブサーバーの間では、多数のコンピューターや端末が HTTP メッセージを中継します。
 ウェブスタックは階層構造であるため、これらの処理のほとんどはトランスポート層、ネットワーク層、物理層のいずれかで行われ、 HTTP 層から見れば透過的であり、パフォーマンスにかなりの影響を与えます。
 アプリケーション層で行われる処理は、通常**プロキシー**と呼ばれます。
 これらは透過的である場合、すなわち受信したリクエストをいかなる場合も変更せずに転送する場合と、透過的ではない場合、すなわちサーバーを通過する前に何らかの形でリクエストを変更する場合とがあります。
 プロキシーはさまざまな機能を実行することがあります。

* キャッシュ（キャッシュは共用、あるいはブラウザーキャッシュのように個人用にできます）
* フィルタリング（アンチウィルススキャンやペアレンタルコントロールなど）
* 負荷分散（複数のサーバーが別々のリクエストに対応できるようにする）
* 認証（さまざまなリソースへのアクセスを制御する）
* ログ記録（履歴情報の保管を可能にする）
HTTP の基本方針
----------

### HTTP はシンプル

HTTP/2 で HTTP メッセージをフレームにカプセル化することにより複雑さが増しましたが、 HTTP は全体的にシンプルで人間が読めるように設計されています。 HTTP メッセージは人間が読んで理解することができ、開発者によるテストを容易にしています。また、初心者に対する複雑さも軽減します。

### HTTP は拡張可能

 HTTP/1.0 で導入された HTTP ヘッダーによって、プロトコルの拡張や実験が容易になっています。
 新しい機能であっても、クライアントとサーバーが新たなヘッダーの意味について単純な合意があれば導入できます。

### HTTP はステートレスであるがセッションレスではない

 HTTP はステートレスです。同じコネクション上であっても、連続的に実行される 2 つのリクエスト間に関係性はありません。
 これは電子商取引のショッピングバスケットなどのように、ユーザーが一貫した方法で特定のページと対話したいときに直接問題になります。
 しかし HTTP の核心がステートレスであっても、 HTTP Cookie によってステートフルなセッションを実現できます。
 ヘッダーの拡張性を利用して、ワークフローに HTTP Cookie が追加されれば、それぞれの HTTP リクエストが同じ状況や同じ状態を共有するためにセッションを作成できるようになります。

### HTTP とコネクション

 コネクションはトランスポート層で制御されますので、 HTTP の範囲から根本的に外れています。
 HTTP は下層のプロトコルがコネクションベースであることに依存はせず、*信頼性がある*、つまりメッセージを失わないこと（少なくともそのような場合にエラーを表示すること）だけを要求します。
 インターネットでもっとも一般的な 2 つのトランスポートプロトコルでは、 TCP には信頼性があり、 UDP には信頼性がありません。
 したがって HTTP は、コネクションベースである TCP 標準に依存しています。

 クライアントとサーバーが HTTP のリクエスト/レスポンスのペアを交換する前に TCP コネクションの確立が必要で、これは複数のやり取りを必要とします。
 HTTP/1.0 の既定の動作は、それぞれのリクエスト/レスポンスのペアに対して個別に TCP コネクションを開くものです。
 これは、複数のリクエストが近く連続して送信されたときに単一の TCP コネクションを共有することよりも非効率です。

 この欠点を軽減するため、 HTTP/1.1 で*パイプライン*（実装が難しいことが立証されました）や*持続的接続*を導入しました。`Connection` ヘッダーを使用して、下層の TCP コネクションを部分的に制御できます。
 HTTP/2 はひとつのコネクションで複数のメッセージを多重化するように進化しました。コネクションををウォーム状態に保つのに役立ち、効率が向上します。

 より HTTP に適したトランスポートプロトコルを設計する実験が進んでいます。
 たとえば Google は、より信頼性があり効率的なトランスポート層プロトコルを提供するため、 UDP 上に構築する QUIC の実験を行っています。

HTTP が制御できること
-------------

 HTTP の拡張性により時間をかけて、ウェブの制御性や機能性が向上できました。
 キャッシュや認証の方法は、 HTTP の草創期から取り扱われてきた機能です。
 対照的に、*オリジン制約*を緩和する機能は 2010 年代にようやく追加されました。

HTTP で制御できる一般的な機能は以下のとおりです。

* *キャッシュ*:
 文書をどのようにキャッシュするかを、 HTTP で制御できます。
 サーバーはプロキシーやクライアントに対して、何をどれだけの間キャッシュするかを指示できます。
 クライアントは中間のキャッシュプロキシーに対して、保存されている文書を無視するよう指示できます。
* *オリジン制約の緩和*:
 のぞき見や他のプライバシー侵害を避けるため、ウェブブラウザーはウェブサイト間を厳密に分割するよう強制しています。
 **同一オリジン**のページだけが、ウェブページの情報すべてにアクセスできます。
 この制約はサーバーにとって負担になりますが、 HTTP ヘッダーでサーバー側の厳密な分割を緩和できます。これにより、さまざまなドメインを情報源とした情報の寄せ集めの文書を作成できます。ただし、このようにするセキュリティ上の理由があります。
* *認証*:
 特定のユーザーしかアクセスできないように保護されたページがあるでしょう。
 基本的な認証は HTTP が提供しており、 `WWW-Authenticate` などのヘッダーを使用するか、 HTTP Cookie を使用した特別なセッションを設定するかします。
* *プロキシーとトンネリング*:
 サーバーやクライアントがイントラネット内に配置されて、他のコンピューターから本当の IP アドレスが見えなくなっていることがよくあります。
 このネットワーク境界を渡るため、 HTTP リクエストはプロキシーを通過します。
 すべてのプロキシーが HTTP プロキシーであるとは限りません。
 たとえば、 SOCKS プロトコルはより低い層で動作します。
 ほかにも FTP などがそれらのプロキシーで処理されることがあります。
* *セッション*:
 HTTP Cookie を使用して、リクエストとサーバーのセッションを関連付けできます。
 これにより HTTP がステートレスプロトコルであるにもかかわらず、セッションを作成できます。
 これは電子商取引のショッピングバスケットだけでなく、出力内容にユーザー設定を適用できるサイトでも有用です。
HTTP のフロー
---------

クライアントがサーバー（最終目的地のサーバーまたは中間のプロキシー）と通信したいとき、クライアントは以下の段階を踏みます。

1. TCP コネクションを開く: TCP コネクションはひとつまたは複数のリクエストを送信したり、回答を受け取ったりするために使用します。
 クライアントは新しいコネクションを開く、既存のコネクションを再使用する、あるいはサーバーに対して複数の TCP コネクションを開くことができます。
2. HTTP メッセージを送信する: HTTP メッセージを（HTTP/2 より前）は人間が読むことができます。
 HTTP/2 では単純なメッセージがフレーム内にカプセル化されており、直接読むことが不可能になりましたが、原理は変わっていません。

```http
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

3. サーバーから送信されたレスポンスを読み取ります。

```http
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html...（ここに、リクエストした 29769 バイトのウェブページが来ます）
```

4. 次のリクエストのために、コネクションを閉じるか再使用する

 HTTP パイプラインが有効である場合は、最初のレスポンスが完全に返るのを待たずに複数のリクエストを送信できます。
 HTTP パイプラインは既存のネットワークで実装するのが難しいことが立証されており、古いソフトウェアと最新バージョンのソフトウェアが共存しています。
 HTTP パイプラインは、 HTTP/2 でフレーム内にリクエストを強力に多重化する機能によって置き換えられました。

HTTP メッセージ
----------

 HTTP/1.1 以前の HTTP メッセージは、人間が読むことができます。
 HTTP/2 ではこれらのメッセージがバイナリ構造の*フレーム*に埋め込まれており、ヘッダーの圧縮や多重化といった最適化が可能になりました。
 本来の HTTP メッセージの部分だけがこのバージョンの HTTP で送信されていても、各メッセージの意味は変わっておらず、クライアントは本来の HTTP/1.1 メッセージを（事実上）再構成します。
 したがって、 HTTP/2 メッセージを HTTP/1.1 形式で理解することは役に立ちます。

HTTP メッセージはリクエストとレスポンスの 2 種類あり、それぞれ固有の形式になっています。

### リクエスト

HTTP リクエストの例です。

![基本的な HTTP リクエスト](/ja/docs/Web/HTTP/Overview/http_request.png)

リクエストは以下の要素で構成されます。

* HTTP メソッド。通常、クライアントが実行したい操作を定義する `GET` や `POST` のような動詞か、`OPTIONS` や `HEAD` のような名詞です。
 一般的にクライアントはリソースを取り込む（`GET` を使用）か HTML フォーム の値を送信する（`POST` を使用）ことを望みますが、場合によってはほかの操作が必要になります。
* 取り込むリソースのパス。状況から明らかであればリソースの URL はこの要素から取り除かれます。たとえばプロトコル (`http://`)、ドメイン（ここでは `developer.mozilla.org`）、TCP ポート（ここでは `80`）が取り除かれます。
* HTTP プロトコルのバージョン。
* サーバーに追加の情報を与える任意のヘッダー。
* `POST` のようなメソッドではレスポンスと同様に、送信するリソースを包含した本体があります。
### レスポンス

レスポンスの例です。

![HTTP レスポンスの画像](/ja/docs/Web/HTTP/Overview/http_response.png)

レスポンスは以下の要素で構成されます。

* 準拠する HTTP プロトコルのバージョン。
* ステータスコード。リクエストが成功したか否か、およびその理由を示します。
* ステータスメッセージ。ステータスコードの簡単な説明ですが、権威はありません。
* リクエストと同様の HTTP ヘッダー。
* （省略可）リソースを含む本体。
HTTP に基づく API
-------------

 最もよく使われている HTTP に基づく API は `XMLHttpRequest` API で、ユーザーエージェントとサーバーの間でデータを交換するために使用することができます。
 新しい `Fetch API` は、同じ機能をより強力で柔軟な一連の機能で提供します。

 他の API、サーバー送信イベントは、サーバーがクライアントにイベントを送信することができる一方通行のサービスで、 HTTP をトランスポートの仕組みとして利用しています。
 `EventSource` インターフェイスを使用して、クライアントは接続を開いてイベントハンドラーを確立します。
 クライアントのブラウザーは HTTP ストリームに届くメッセージを自動的に適切な `Event` オブジェクトに変換します。それからイベントの`型`が分かればその型に登録されているイベントハンドラーに配信し、型に対してイベントハンドラーが設定されていない場合は、 `onmessage` イベントハンドラーに配信します。

まとめ
---

HTTP は容易に使用できる、拡張可能なプロトコルです。クライアントサーバー構造と単純にヘッダーを追加できる機能性を組み合わせて、 HTTP はウェブの機能拡張に合わせて進化できます。

 HTTP/2 でパフォーマンスを向上するため、フレーム内に HTTP メッセージを埋め込むことにより複雑さがいくらか増しましたが、メッセージの基本的な構造は HTTP/1.0 から同じままです。
 セッションのフローは依然として単純であり、フローの調査やシンプルな HTTP メッセージモニターでデバッグすることができます。


典型的な HTTP セッション - HTTP

典型的な HTTP セッション
===============

HTTP のようなクライアントサーバープロトコルでは、セッションが 3 つの段階で構成されます。

1. クライアントは TCP コネクション (トランスポート層が TCP ではない場合は、他の適切なコネクション) を確立します。
2. クライアントは要求を送り、回答を待ちます。
3. サーバは要求を処理して、ステータスコードや適切なデータを提供する回答を返信します。

HTTP/1.1 では第 3 段階の後にコネクションは閉じられなくなり、クライアントはさらに要求を発行することができます。つまり、第 2 段階と第 3 段階を複数回行うことができます。

コネクションの確立
---------

クライアントサーバープロトコルでは、クライアントがコネクションを確立します。HTTP のコネクションを開くとは、下層のトランスポート層のコネクションを確立することであり、これは通常 TCP です。

コンピューター上の HTTP サーバー用の、 TCP の既定のポートは 80 番です。8000 番や 8080 番など、ほかのポートを使用することもできます。読み込むページの URL はドメイン名とポート番号の両方を含みますが、後者は 80 番である場合に省略できます。詳しくは Identifying resources on the Web をご覧ください。

**メモ:** クライアントサーバーモデルでは、明示的な要求なくサーバーがクライアントにデータを送信することを認めていません。この問題を回避するために、ウェブ開発者はいくつかの技術を使用しています。 `XMLHTTPRequest` や `Fetch` API で定期的にサーバーに ping を送ったり、 WebSockets API や同様のプロトコルを使用したりします。

クライアントの要求の送信
------------

コネクションを確立すると、ユーザーエージェントは要求を送信できます (ユーザーエージェントは一般的にウェブブラウザーですが、ほかにもクローラーなどがあります)。クライアントの要求は CRLF (キャリッジリターンに続いてラインフィード) で区切られたテキストのディレクティブで構成され、3 つのブロックに分けられます。

1. 最初の行は、要求メソッドの後に次の引数が続きます。
    * 文書のパス、すなわち絶対 URL からプロトコル名とドメイン名を除いたものです。
    * HTTP プロトコルのバージョン。
2. 後続の行は HTTP ヘッダーであり、サーバーに対してどの種類 (例えば、言語や MIME タイプ) のデータが適切かを示す情報や、サーバーの動作を変える (例えば、すでにキャッシュされている場合は回答を送信しない) データを与えます。これらの HTTP ヘッダーは空行で終わるブロックを構成します。
3. 最後のブロックは省略可能なデータブロックで、主に POST メソッドで使用される追加のデータを含みます。
### 要求の例

developer.mozilla.org のルートページ、すなわち http://developer.mozilla.org/ を読み込む、また可能であればユーザーエージェントはフランス語のページを希望することをサーバに伝えます:
```

GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

ヘッダーブロックとデータブロックを分けている、最後の空行に注意してください。この例は HTTP ヘッダーに `Content-Length` がありませんので、空のデータブロックが与えられてヘッダーの終わりを示しており、サーバーはこの空行を受け取るとただちに要求を処理できます。

フォームの入力結果を送信する例です。
```

POST /contact_form.php HTTP/1.1
Host: developer.mozilla.org
Content-Length: 64
Content-Type: application/x-www-form-urlencoded

name=Joe%20User&request=Send%20me%20one%20of%20your%20catalogue
```

### 要求メソッド

HTTP では、リソースに対して実行したいアクションを示す要求メソッドのセットを定義しています。要求メソッドには名詞も存在しますが、 HTTP 動詞と言われることがあります。 `GET` と `POST` が最も一般的です。

* `GET` メソッドは、指定したリソースのデータを要求します。 `GET` を使用する要求は、データの取り込みに限ります。
* `POST` メソッドはサーバーにデータを送信しますので、データの状態を変更できます。これは、 HTML フォーム用によく使用されるメソッドです。
サーバー応答の構造
---------

接続したエージェントが要求を送信すると、ウェブサーバーはその要求を処理して、最終的に応答を返信します。クライアントの要求と同様にサーバーの応答はテキストのディレクティブで構成され、それらは CRLF で区切られており、3 つのブロックに分けられます:

1. 最初の行は*ステータス行*で、受け入れた HTTP バージョンとステータス要求で構成されます (そして、人間に読めるテキストで意味を簡単に示します)。
2. 後続の行はそれぞれ具体的な HTTP ヘッダーを表しており、クライアントに対して送信したデータに関する情報 (例えば種類、サイズ、圧縮方法、キャッシュ情報) を与えます。クライアントの要求の HTTP ヘッダーブロックと同様に、これらの HTTP ヘッダーも空行で終わるブロックを構成します。
3. 最後のブロックはデータブロックで、任意のデータを含みます。
### 応答の例

成功したウェブページの応答です:
```

HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html... (ここにサイズが 29769 バイトの、要求されたウェブページが置かれます)
```

要求されたリソースが永続的に移動されたことの通知です。
```

HTTP/1.1 301 Moved Permanently
Server: Apache/2.2.3 (Red Hat)
Content-Type: text/html; charset=iso-8859-1
Date: Sat, 09 Oct 2010 14:30:24 GMT
Location: https://developer.mozilla.org/ (これはリソースの新しいリンクです。ユーザーエージェントはこちらを読み込むでしょう)
Keep-Alive: timeout=15, max=98
Accept-Ranges: bytes
Via: Moz-Cache-zlb05
Connection: Keep-Alive
X-Cache-Info: caching
X-Cache-Info: caching
Content-Length: 325 (ユーザーエージェントがリンクをたどれない場合に表示する、既定のページを含むコンテンツです)

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://developer.mozilla.org/">here</a>.</p>
<hr>
<address>Apache/2.2.3 (Red Hat) Server at developer.mozilla.org Port 80</address>
</body></html>
```

要求されたリソースが存在しないことの通知です。
```

HTTP/1.1 404 Not Found
Date: Sat, 09 Oct 2010 14:33:02 GMT
Server: Apache
Last-Modified: Tue, 01 May 2007 14:24:39 GMT
ETag: "499fd34e-29ec-42f695ca96761;48fe7523cfcc1"
Accept-Ranges: bytes
Content-Length: 10732
Content-Type: text/html

<!DOCTYPE html... (欠けているリソースをユーザが見つけることを支援する、サイト毎にカスタマイズされたページを含みます)
```

### 応答ステータスコード

HTTP 応答ステータスコード は、特定の HTTP 要求が正常に完了したかを示します。応答は情報応答、成功応答、リダイレクション、クライアントエラー、サーバーエラーの 5 つのクラスに分類されます。

* `200`: OK. 要求は成功しました。
* `301`: Moved Permanently. この応答コードは、要求したリソースの URI が変更されたことを表します。
* `404`: Not Found. サーバーは、要求されたリソースを見つけることができません。
関連情報
----

* ウェブ上のリソースの識別
* HTTP ヘッダー
* HTTP 要求メソッド
* HTTP 応答ステータスコード


Ogg メディア用のサーバーの設定 - HTTP

Ogg メディア用のサーバーの設定
=================

HTML `<audio>` 要素と `<video>` 要素を使用すると、ユーザーはプラグインやその他のソフトウェアをインストールする必要なくメディアを表示できます。サーバーが Ogg メディアを正しく配信するためには、いくつか設定が必要な場合があります。

正しい MIME タイプの Ogg メディアを提供する
---------------------------

\*.ogg and \*.ogv files containing video (possibly with an audio track as well, of course), should be served with the `video/ogg` MIME type. \*.oga and \*.ogg files containing only audio should be served with the `audio/ogg` MIME type.

If you don't know whether the Ogg file contains audio or video, you can serve it with the MIME type application/ogg, and Gecko will treat it as a video file.

Most servers don't by default serve Ogg media with the correct MIME types, so you'll likely need to add the appropriate configuration for this.

For Apache, you can add the following to your configuration:
```

AddType audio/ogg .oga
AddType video/ogg .ogv
AddType application/ogg .ogg
```

HTTP 1.1 byte range requests を正しく処理する
-------------------------------------

In order to support seeking and playing back regions of the media that aren't yet downloaded, Gecko uses HTTP 1.1 byte-range requests to retrieve the media from the seek target position. In addition, Gecko uses byte-range requests to seek to the end of the media (assuming you serve the `Content-Length` header) in order to determine the duration of the media.

Your server should accept the `Accept-Ranges``: bytes` HTTP header if it can accept byte-range requests. It must return `206``: Partial content` to all byte range requests; otherwise, browsers can't be sure you actually support byte range requests.

Your server must also return "`206: Partial Content`" for the request "`Range: bytes=0-`" as well.

通常のキーフレームを含める
-------------

When Gecko seeks through Ogg media to a specified time, it has to seek to the nearest key frame before the seek target, then download and decode the video from there until the requested target time. The farther apart your key frames are, the longer this takes, so it's helpful to include key frames at regular intervals.

By default, `ffmpeg2theora` uses one key frame every 64 frames (or about every 2 seconds at 30 frames per second), which works pretty well.

**メモ:** Of course, the more key frames you use, the larger your video file is, so you may need to experiment a bit to get the right balance between file size and seek performance.

preload 属性の使用を検討する
------------------

The HTML `<audio>` and `<video>` elements provide the `preload` attribute, which tells Gecko to attempt to download the entire media when the page loads. Without `preload`, Gecko only downloads enough of the media to display the first video frame, and to determine the media's duration.

`preload` is off by default, so if getting to video is the point of your web page, your users may appreciate it if you include `preload` in your video elements.

古いバージョンの Firefox の設定
--------------------

### Serve X-Content-Duration headers

**メモ:** As of Firefox 41, the `X-Content-Duration` header is no longer supported. See Firefox バグ 1160695 for more details.

The Ogg format doesn't encapsulate the duration of media, so for the progress bar on the video controls to display the duration of the video, Gecko needs to determine the length of the media using other means.

There are two ways Gecko can do this. The best way is to offer an `X-Content-Duration` header when serving Ogg media files. This header provides the duration of the video in seconds (**not** in HH:MM:SS format) as a floating-point value.

For example, if the video is 1 minute and 32.6 seconds long, this header would be:
```

X-Content-Duration: 92.6
```

If your server provides the `X-Content-Duration` header when serving Ogg media, Gecko doesn't have to do any extra HTTP requests to seek to the end of the file to calculate its duration. This makes the entire process much more efficient as well as more accurate.

As an inferior alternative, Gecko can estimate the video length based on the Content-Length. See next point.

### Don't use gzip/deflate compression

One common way to reduce the load on a web server is to use gzip or deflate compression when serving to a supporting web browser. When Firefox requests an Ogg media, it advertises that it can handle a gzipped or deflated response; the HTTP request includes the `Accept-Encoding: gzip,deflate` header. But despite Firefox advertising that it supports gzip/deflate, you probably don't want to gzip or deflate Ogg media. If you serve an Ogg media compressed, Firefox won't be able to seek in the media, or determine its duration. Since the video/audio data in Ogg files is already compressed, gzip/deflate won't actually save you much bandwidth anyway, so you probably want to disable compression when serving Ogg files.

Also, Apache servers don't send the Content-Length response header if gzip encoding is used.

**メモ:** Starting in Gecko 2.0, Gecko will no longer request gzip or deflate compression when downloading media. The above is only relevant for Firefox 3.5/3.6.

### Getting the duration of Ogg media

You can use the `oggz-info` tool to get the media duration; this tool is included with the `oggz-tools` package. The output from `oggz-info` looks like this:
```

 $ oggz-info /g/media/bruce_vs_ironman.ogv
 Content-Duration: 00:01:00.046

 Skeleton: serialno 1976223438
         4 packets in 3 pages, 1.3 packets/page, 27.508% Ogg overhead
         Presentation-Time: 0.000
         Basetime: 0.000

 Theora: serialno 0170995062
         1790 packets in 1068 pages, 1.7 packets/page, 1.049% Ogg overhead
         Video-Framerate: 29.983 fps
         Video-Width: 640
         Video-Height: 360

 Vorbis: serialno 0708996688
         4531 packets in 167 pages, 27.1 packets/page, 1.408% Ogg overhead
         Audio-Samplerate: 44100 Hz
         Audio-Channels: 2
```

Note that you can't simply serve up the reported Content-Duration line reported by `oggz-info`, because it's reported in HH:MM:SS format. You'll need to convert it to seconds only, then serve that as your `X-Content-Duration` value. Just parse out the HH, MM, and SS into numbers, then do (HH\*3600)+(MM\*60)+SS to get the value you should report.

It's important to note that it appears that `oggz-info` makes a read pass of the media in order to calculate its duration, so it's a good idea to store the duration value in order to avoid lengthy delays while the value is calculated for every HTTP request of your Ogg media.

関連情報
----

* Video and audio content
* Media formats supported by the audio and video elements


HTTP のリソースと仕様書 - HTTP

HTTP のリソースと仕様書
==============

HTTP が最初に規定されたのは 1990 年代初頭のことです。拡張性を念頭に置いて設計されていますが、何年にもわたって何度も追加されてきました。このため、その仕様は多くの仕様書に散在しています (実験的に放棄された拡張の中に埋もれています)。このページでは、 HTTP に関連するリソースをリストアップしています。

| 仕様書 | 表題 | 状態 |
| --- | --- | --- |
| RFC 9110 | HTTP Semantics | インターネット標準 |
| RFC 9111 | HTTP Caching | インターネット標準 |
| RFC 9112 | HTTP/1.1 | インターネット標準 |
| RFC 9113 | HTTP/2 | 標準化への提唱 |
| RFC 9114 | HTTP/3 | 標準化への提唱 |
| RFC 5861 | HTTP Cache-Control Extensions for Stale Content | 情報提供 |
| RFC 8246 | HTTP Immutable Responses | 標準化への提唱 |
| RFC 6265 | HTTP State Management Mechanism *Defines Cookies* | 標準化への提唱 |
| Draft spec | Cookie Prefixes | IETF 草稿 |
| Draft spec | Same-Site Cookies | IETF 草稿 |
| Draft spec | Deprecate modification of 'secure' cookies from non-secure origins | IETF 草稿 |
| RFC 2145 | Use and Interpretation of HTTP Version Numbers | 情報提供 |
| RFC 6585 | Additional HTTP Status Codes | 標準化への提唱 |
| RFC 7725 | An HTTP Status Code to Report Legal Obstacles | 標準化過程 |
| RFC 2397 | The "data" URL scheme | 標準化への提唱 |
| RFC 3986 | Uniform Resource Identifier (URI): Generic Syntax | インターネット標準 |
| RFC 5988 | Web Linking *Defines the `Link` header* | 標準化への提唱 |
| Experimental spec | Hypertext Transfer Protocol (HTTP) Keep-Alive Header | 情報提供 (古いもの) |
| Draft spec | HTTP Client Hints | IETF 草稿 |
| RFC 7578 | Returning Values from Forms: multipart/form-data | 標準化への提唱 |
| RFC 6266 | Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP) | 標準化への提唱 |
| RFC 2183 | Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field *Only a subset of syntax of the `Content-Disposition` header can be used in the context of HTTP messages.* | 標準化への提唱 |
| RFC 7239 | Forwarded HTTP Extension | 標準化への提唱 |
| RFC 6455 | The WebSocket Protocol | 標準化への提唱 |
| RFC 5246 | The Transport Layer Security (TLS) Protocol Version 1.2 *This specification has been modified by subsequent RFCs, but these modifications have no effect on the HTTP protocol.* | 標準化への提唱 |
| RFC 8446 | The Transport Layer Security (TLS) Protocol Version 1.3 *Supersedes TLS 1.2.* | 標準化への提唱 |
| RFC 2817 | Upgrading to TLS Within HTTP/1.1 | 標準化への提唱 |
| RFC 7541 | HPACK: Header Compression for HTTP/2 | 標準化過程 |
| RFC 7838 | HTTP Alternative Services | 標準化過程 |
| RFC 7301 | Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension *Used to negotiate HTTP/2 at the transport to save an extra request/response round trip.* | 標準化への提唱 |
| RFC 6454 | The Web Origin Concept | 標準化への提唱 |
| Fetch | Cross-Origin Resource Sharing | ライブ標準 |
| RFC 7034 | HTTP Header Field X-Frame-Options | 情報提供 |
| RFC 6797 | HTTP Strict Transport Security (HSTS) | 標準化への提唱 |
| Upgrade Insecure Requests | Upgrade Insecure Requests | 勧告候補 |
| Content Security Policy 1.0 | Content Security Policy 1.0 *CSP 1.1 and CSP 3.0 doesn't extend the HTTP standard* | 廃止 |
| Microsoft document | Specifying legacy document modes\* *Defines X-UA-Compatible* | メモ |
| RFC 5689 | HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV) *These extensions of the Web, as well as CardDAV and CalDAV, are out-of-scope for HTTP on the Web. Modern APIs for application are defines using the RESTful pattern nowadays.* | 標準化への提唱 |
| RFC 2324 | Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) | エイプリルフールのジョーク仕様 |
| RFC 7168 | The Hyper Text Coffee Pot Control Protocol for Tea Efflux Appliances (HTCPCP-TEA) | エイプリルフールのジョーク仕様 |
| HTML Living Standard | HTML *Defines extensions of HTTP for Server-Sent Events* | ライブ標準 |
| Reporting API | `Report-To` header | 草稿 |
| Draft spec | Expect-CT Extension for HTTP | IETF 草稿 |


HTTP Cookie の使用 - HTTP

HTTP Cookie の使用
===============

**HTTP Cookie** (ウェブ Cookie、ブラウザー Cookie) は、サーバーがユーザーのウェブブラウザーに送信する小さなデータであり、ブラウザーに保存され、その後のリクエストと共に同じサーバーへ返送されます。一般的には、 2 つのリクエストが同じブラウザーから送信されたものであるかを知るために使用されます。例えば、ユーザーのログイン状態を維持することができます。 Cookie は、ステートレスな HTTP プロトコルのためにステートフルな情報を記憶します。

Cookie は主に、以下の 3 つの用途で使用されます。

セッション管理

ログイン、ショッピングカート、ゲームのスコア、またはその他のサーバーが覚えておくべきもの

パーソナライズ

ユーザー設定、テーマ、その他の設定

トラッキング

ユーザーの行動の記録および分析

Cookie は、クライアント側の汎用的な記憶領域として使用されたことがあります。これは他にクライアントへデータを保存する手段がなかった頃は合理的でしたが、現在では新しいストレージ API を使用することが推奨されています。 Cookie はすべてのリクエストで送信されるので、（特にモバイルデータ通信で）性能を悪化させる可能性があります。クライアントストレージ向けの新しい API として、ウェブストレージ API (`localStorage` および `sessionStorage`) と IndexedDB があります。

**メモ:** 保存された Cookie (およびウェブページが使用できる他のストレージ) を確認するには、開発ツールのストレージインスペクターを有効化して、ストレージのツリーで Cookie を選択してください。

Cookie の作成
----------

HTTP リクエストを受け取った後、サーバーはレスポンスで `Set-Cookie` ヘッダーを送信することができます。通常 Cookie はブラウザーに保存され、また Cookie は同じサーバーに対して行われるリクエストと共に HTTP の `Cookie` ヘッダーの中で送信されます。有効期限や期間を設定することができ、その後は Cookie が送信されなくなります。特定のドメインやパスへの追加の制約を設定することができ、Cookie をどこに送信するかを制限することができます。以下で言及されているヘッダー属性の詳細については、 `Set-Cookie` のリファレンス記事を参照してください。

### `Set-Cookie` ヘッダーと `Cookie` ヘッダー

HTTP の `Set-Cookie` レスポンスヘッダーは、サーバーがユーザーエージェントへ Cookie を送信するために使用します。単純な Cookie は次のように設定されます。

```http
Set-Cookie: <cookie-name>=<cookie-value>
```

これは、サーバーからクライアントへ Cookie の組み合わせを保存するよう指示することを表します。

```http
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy\_cookie=choco
Set-Cookie: tasty\_cookie=strawberry

[ページの内容]
```

また、そのサーバーへのその後のすべてのリクエストにおいて、ブラウザーは以前格納されたすべての Cookie を、 `Cookie` ヘッダーを使用してサーバーへ送信します。

```http
GET /sample\_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy\_cookie=choco; tasty\_cookie=strawberry
```

**メモ:** 様々なサーバー側アプリケーションにおける `Set-Cookie` ヘッダーの使い方を紹介します。

* PHP
* Node.JS
* Python
* Ruby on Rails

### Cookie の持続時間の定義

Cookie の持続時間は 2 通りの方法で定義することができます。

* *セッション* Cookie は現在のセッションが終了すると削除されます。ブラウザーはいつ「現在のセッション」が終わったと見なすかを定義し、ブラウザーによっては再起動時に*セッションの復元*を使用することができます。そのため、結果的にセッション Cookie が無期限に持続することがあります。
* *持続的* Cookie は、 `Expires` 属性で指定された時刻、または `Max-Age` で指定された期間が経過した後に削除されます。

例を示します。

```http
Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;
```

**メモ:** `Expires` の日付を設定した場合、設定された日時はサーバーではなく、Cookie が設定されるクライアントの日時に関連します。

サイトがユーザーを認証する場合、ユーザーが認証するたびに、すでに存在するセッション Cookie も含めて、セッション Cookie を再生成して再送する必要があります。この手法は、第三者がユーザーのセッションを再利用するセッション固定攻撃を防ぐのに役立ちます。

### Cookie へのアクセス制限

Cookie が安全に送信され、意図しない第三者やスクリプトからアクセスされないようにするには、 `Secure` 属性と `HttpOnly` 属性の 2 つの方法があります。

`Secure` 属性がついた Cookie は HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されないため、中間者攻撃者が簡単にアクセスすることはできません。(URL に `http:` を含む) 安全でないサイトは、 `Secure` 属性を使用して Cookie を設定することができません。ただし、`Secure` によって Cookie 内の機密情報へのアクセスをすべて防げると思ってはいけません。例えば、クライアントのハードディスクへアクセスすることで読み取られる可能性があります。

`HttpOnly` 属性を持つ Cookie は、 JavaScript の `Document.cookie` API にはアクセスできません。サーバーに送信されるだけです。例えば、サーバー側のセッションを持続させる Cookie は JavaScript が利用する必要はないので、 `HttpOnly` 属性をつけるべきです。この予防策は、クロスサイトスクリプティング (XSS) 攻撃を緩和するのに役立ちます。

例を示します。

```http
Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly
```

### Cookie の送信先の定義

`Domain` および `Path` 属性は、Cookie の*スコープ*、つまり Cookie を送信する対象の URL を定義します。

#### Domain 属性

`Domain` 属性は、Cookie を受信することができるホストを指定します。サーバーが `Domain` を指定しなかった場合、ブラウザーは既定でドメインを Cookie を設定したのと同じホストとし、*サブドメインは除外します*。 `Domain` が指定された場合、サブドメインは常に含まれます。したがって、 `Domain` を指定すると省略時よりも制限が緩和されます。ただし、サブドメイン間でユーザーに関する情報を共有する場合は有用になるでしょう。

例えば、`Domain=mozilla.org` を設定すると、`developer.mozilla.org` のようなサブドメインも含まれます。

#### Path 属性

`Path` 属性は、 `Cookie` ヘッダーを送信するためにリクエストされた URL の中に含む必要がある URL のパスを示します。 `%x2F` ("/") の文字はディレクトリー区切り文字として解釈され、サブディレクトリーにも同様に一致します。

例えば、`Path=/docs` を設定すると、以下のリクエストパスに一致します。

* `/docs`
* `/docs/`
* `/docs/Web/`
* `/docs/Web/HTTP`

ただし、これらのリクエストパスには一致しません。

* `/`
* `/docsets`
* `/fr/docs`

#### SameSite 属性

`SameSite` 属性により、サーバーがサイト間リクエスト (ここでサイトは登録可能なドメインによって定義されます) と一緒に Cookie を送るべきではないことを要求することができます。これは、クロスサイトリクエストフォージェリー攻撃 (CSRF) に対していくらかの防御となります。取ることができる値は `Strict`, `Lax`, `None` の 3 つです。

`Strict` では、ブラウザーは Cookie の元サイトからのリクエストに対してのみ Cookie を送ります。
 `Lax` も同様ですが、ユーザーが Cookie の元サイトに移動したときに（たとえユーザーが異なる形のサイトから来たとしても）ブラウザーは Cookie を送信します。
 例えば、外部サイトからリンクをたどった場合です。 `None` は Cookie を発生元サイトへリクエストとサイト間のリクエストの両方で送信されますが、*安全なコンテキスト*でのみ送信されます（つまり、 `SameSite=None`なら `Secure` 属性も設定する必要があります）。
 もし `SameSite` 属性が設定されていない場合、 Cookie は `Lax` として扱われます。

次に例を示します。

```http
Set-Cookie: mykey=myvalue; SameSite=Strict
```

**メモ:** `SameSite` に関する標準規格が最近変更されました（MDN で文書化している上記の動作は新しい動作です）。
 ブラウザーの特定の版がこの属性をどのように扱うかの情報については、 Cookie のブラウザー互換性 (en-US)一覧表を参照してください。

* `SameSite=Lax` は `SameSite` が指定されなかった場合の新しい既定値です。
 以前は、 Cookie は既定ですべてのリクエストに送信されていました。
* Cookie に `SameSite=None` が付いた場合は、 `Secure` 属性も指定することになりました（安全なコンテキストが必要になりました）。
* 同じドメインの Cookie であっても、異なるスキーム (`http:` か `https:` か) を使用して送信された場合は同じサイトと見なされなくなりました。

#### Cookie の接頭辞

Cookie の仕組みの設計では、 Cookie が安全なオリジンに設定されているかどうか、 Cookie が当初は*どこに*設定されたのかをサーバーが確認することができないようになっています。

サブドメイン上にある脆弱性のあるアプリケーションが `Domain` 属性を使用して Cookie を設定すると、ほかのすべてのサブドメインで Cookie にアクセスできるようにすることができます。この仕組みは*セッション固定*攻撃で悪用される可能性があります。主な対策方法はセッション固定化を参照してください。

しかし、多層防御として、 Cookie に関する特定の事実を主張するために *Cookie の接頭辞*を使うことが可能です。以下の 2 つの接頭辞が利用可能です。

`__Host-`

Cookie 名にこの接頭辞がついている場合、 `Set-Cookie` ヘッダーが受け入れられるのは `Secure` 属性で指定されており、安全なオリジンから送信されており、 `Domain` 属性を含んで*おらず*、 `Path` 属性が `/` に設定されている場合のみです。この場合、これらの Cookie は「ドメインにロックされている」と見なすことができます。

`__Secure-`

Cookie 名にこの接頭辞がある場合、 `Set-Cookie` ディレクティブが受け入れられるのは、 `Secure` であり、安全なオリジンから送信されている場合のみです。これは `__Host-` 接頭辞よりも弱いものです。

これらの接頭辞が付いていて、制約に適合していない Cookie は、送られてもブラウザーが拒否します。これにより、仮にサブドメインで接頭辞の付いた Cookie を作成した場合、サブドメインに限定されるか、完全に無視されるかします。アプリケーションサーバーは、ユーザーが認証されているか、あるいは CSRF トークンが正しいかどうかを判断するときに、特定の Cookie 名をチェックするだけなので、これはセッションの固定化に対する防御手段として効果的に機能します。

**メモ:** アプリケーションサーバ上では、ウェブアプリケーションは接頭辞を含む完全な Cookie 名をチェック*しなければなりません*。—ユーザーエージェントは、リクエストの `Cookie` ヘッダーを送信する前に Cookie から接頭辞を削除*しません*。

Cookie の接頭辞とブラウザー対応の現在の状態については、 Set-Cookie リファレンス記事の接頭辞の節を参照してください。

#### JavaScript での Document.cookies を使用したアクセス

`Document.cookie` プロパティを使用して新しい Cookie を作成することができますし、 `HttpOnly` フラグが設定されていない限り、既存の Cookie に JavaScript からアクセスすることもできます。

```js
document.cookie = "yummy\_cookie=choco";
document.cookie = "tasty\_cookie=strawberry";
console.log(document.cookie);
// "yummy\_cookie=choco; tasty\_cookie=strawberry" とログ出力
```

JavaScript で生成された Cookie は `HttpOnly` フラグを含むことができません。

後述するセキュリティの節に記載したとおり、セキュリティの影響に注意してください。JavaScript で使用できる Cookie は、XSS によって盗まれる可能性があります。

セキュリティ
------

**メモ:** 情報を Cookie に保存するときは、すべての Cookie の値がエンドユーザーから見え、変更できることを理解しておいてください。アプリケーションによっては、サーバー側で検索される不透明な識別子を使用するか、 JSON ウェブトークンのような代替の認証/機密性メカニズムを調べたほうが良いかもしれません。

Cookie への攻撃を緩和する方法には次のようなものがあります。

* `HttpOnly` 属性を使用して、 JavaScript から Cookie の値にアクセスすることを防ぎます。
* 機密情報 (認証を示す場合など) のために使用された Cookie は、持続時間を短く、 `SameSite` 属性を `Strict` または `Lax` に設定してください。 (上記の SameSite Cookie を参照。) SameSite に対応しているブラウザーでは、これは、認証 Cookie がオリジン間リクエストと一緒に送信されないようにする効果があるので、そのようなリクエストはそのアプリケーションサーバーに対して事実上認証されていないことになります。
トラッキングとプライバシー
-------------

### サードパーティの Cookie

 Cookie はドメインとスキーム（`http` や `https` など）に関連付けられ、 `Set-Cookie` の `Domain` 属性が設定された場合はサブドメインにも関連付けられます。
 Cookie のドメインとスキームが現在のページと一致している場合、その Cookie はこのページと同じサイトからのものと見なされ、*ファーストパーティ Cookie* と呼ばれます。

 ドメインとスキームが異なる場合、その Cookie は同じサイトのものとはみなされず、*サードパーティ Cookie* と呼ばれます。
 ウェブページをホスティングしているサーバーがファーストパーティ Cookie を設定する一方で、ページには他のドメインのサーバーに保存されている画像やその他のコンポーネント (例えば、広告バナー) が含まれている場合があり、サードパーティ Cookie を設定することがあります。
 これらは主にウェブ上での広告やトラッキングに使用されます。
 例えば Google が使用している Cookie の種類を参照してください。

サードパーティのサーバーは、複数のサイトにアクセスした際に同じブラウザーから送信された Cookie に基づいて、ユーザーの閲覧履歴や習慣のプロファイルを構築することができます。 Firefox は既定で、トラッカーを含むことが知られているサードパーティの Cookie をブロックします。サードパーティの Cookie (またはトラッキング Cookie ) は、他のブラウザーの設定や拡張機能によってもブロックされる場合があります。 Cookie をブロックすると、一部のサードパーティ製コンポーネント (ソーシャルメディアウィジェットなど) が意図した通りに機能しなくなることがあります。

ユーザーのプライバシーを尊重し、サードパーティの追跡を最小限に抑えたい開発者にとって、有益な機能がいくつか使用されています。

* サーバーは Cookie の SameSite 属性 (en-US)を設定することで、サードパーティーの Cookie を送るかどうか指定することができます（そしてそうすべきです）。
* Cookies Having Independent Partitioned State (CHIPS) (en-US) は、開発者が、最上位のサイトごとに別個の Cookie ジャーを持つ、分割されたストレージへの Cookie のオプトインができるようにします。これは、サードパーティのトラッキングに Cookie を使用することを許可しないブラウザーで、サードパーティの Cookie の有効な非トラッキング用途が引き続き動作するようにするものです。
### Cookie に関する規制

Cookie の使用を対象とした法規制には、以下のようなものがあります。

* EU の 一般データ保護規則 (GDPR)
* EU の ePrivacy 指令
* カリフォルニア州消費者プライバシー法

これらの規制は、これらの管轄区域（EU とカリフォルニア州、特にカリフォルニア州の法律は総収入が 2,500 万ドルを超える事業体にのみ適用されるという注意事項がある）のユーザーがアクセスする*全世界*のウェブ上のあらゆるサイトに適用されるため、世界的な広がりを持っています。

これらの規制の要件には次のようなものがあります。

* サイトが Cookie を使用することをユーザーに通知すること。
* ユーザーが一部またはすべての Cookie をオプトアウトできるようにすること
* ユーザーが Cookie を受け取らなくても、サービスの大部分を利用できるようにすること。

地域によっては、他にも Cookie の使用を管理する規制があるかもしれません。これらの規制を理解し遵守することは、自分自身の責任となります。これらの規制を遵守するのに役立つ「Cookie 禁止」コードを提供している会社もあります。

ブラウザーに情報を格納する他の方法
-----------------

ブラウザーにデータを保存する別のアプローチとして、 Web Storage API があります。 window.sessionStorage と window.localStorage プロパティはセッション Cookie と持続的 Cookie に対応していますが、ストレージの容量制限が Cookie より大きく、サーバーに送信されることはありません。より構造化された大量のデータは、 IndexedDB API またはその上に構築されたライブラリを使用して保存することができます。

「ゾンビ」 Cookie と呼ばれる、 Cookie が削除された後に再作成されるようにするための他の技術が作成されています。これらの技術は、ユーザーのプライバシーとユーザー制御の原則に違反し、データプライバシー規制に違反する可能性があり、これらの技術を使用しているウェブサイトが法的責任にさらされる可能性があります。

関連情報
----

* `Set-Cookie`
* `Cookie`
* `Document.cookie`
* `Navigator.cookieEnabled`
* SameSite Cookie (en-US)
* ストレージインスペクターを使った Cookie の調査
* Cookie specification: RFC 6265
* HTTP cookie on Wikipedia
* Cookies, the GDPR, and the ePrivacy Directive


HTTP クライアントヒント - HTTP

HTTP クライアントヒント
==============

**クライアントヒント** (Client hints) は、サーバーがクライアントに積極的にリクエストすることで、端末、ネットワーク、ユーザー、およびユーザーエージェント固有の環境設定に関する情報を取得することができる HTTP リクエストヘッダー フィールド群です。
 サーバーは、クライアントが提供することを選んだ情報に基づいて、送信するリソースを決定することができます。

一連の「ヒント」ヘッダーは、 HTTP ヘッダー のトピックに挙げられている他、下記にもまとめています。

概要
--

 サーバーはクライアントヒントに対応していることを知らせる必要があります。 `Accept-CH` を使用して、受信したいヒントを指定します。
 クライアントヒントに対応しているクライアントは、`Accept-CH` ヘッダーを受け取ると、列挙されているクライアントヒントヘッダーの一部または全部を、それ以降のリクエストに追加することを選択することができます。

例えば、下記のレスポンスの `Accept-CH` の後で、クライアントは `Width` (en-US)、 `Downlink` (en-US)、`Sec-CH-UA` (en-US) ヘッダーを以降のすべてのリクエストに付加することができます。

```http
Accept-CH: Width, Downlink, Sec-CH-UA
```

 この手法は、サーバーが有益に処理することができる情報のみをリクエストされるという点で効率的です。
 また、どの情報を安全に共有できるかを決めるのはクライアント次第という点で、比較的「プライバシー保護」にもなっています。

リクエストされなかった場合、クライアントイベントによって送信される可能性のある、低エントロピーのクライアントヒントヘッダーも少しあります。

**メモ:** クライアントヒントは、 HTML で `<meta>` 要素に `http-equiv` 属性を使用して指定することも可能です。

```html
<meta http-equiv="Accept-CH" content="Width, Downlink, Sec-CH-UA" />
```

キャッシュとクライアントヒント
---------------

 レスポンスで送信されるリソースを決定するクライアントヒントは、一般に、影響を受けるレスポンスの `Vary` ヘッダーに記載すべきです。
 これにより、ヒントヘッダーの値が異なる場合に、それぞれ別のリソースがキャッシュされることが保証されます。

```http
Vary: Accept, Width, ECT
```

 値が頻繁に変更されるクライアントヒントヘッダについては、 `Vary` を指定しないか、 他の方法を使用したほうがよいでしょう。これは、リソースを効果的にキャッシュできなくしてしまうからです。( それぞれの固有の値に対して、新しいキャッシュ項目が作成されます)。
 これは特に `Downlink` (en-US) や `RTT` (en-US) のようなネットワーククライアントヒントに当てはまります。
 詳細な情報は、HTTP キャッシュ > レスポンスの変化 を参照してください。

ヒントの期限
------

 サーバーは、取得したいクライアントヒントヘッダーを `Accept-CH` レスポンスヘッダで指定します。
 ユーザーエージェントはリクエストされたクライアントヒントヘッダー、または少なくともそのサーバーと共有するサブセットを、現在の閲覧セッションにおけるそれ以降のすべてのリクエストに付加します。

言い換えれば、特定のヒント集合に対するリクエストは、ブラウザーが終了するまで期限切れになりません。

 サーバーが受け取りたいクライアントヒントの集合を置き換えるには、 `Accept-CH` レスポンスヘッダーを新しいリストで再送することで行うことができます。
 例えば、何もリクエストしないようにするには、空のリストで `Accept-CH` を送ります。

低エントロピーヒント
----------

クライアントヒントは、高エントロピーと低エントロピーのヒントに大別されます。

 低エントロピーヒントは、特定のユーザーを「フィンガープリント」（識別）するために使用される可能性がある情報を多くは与えないものです。
 これらは、サーバーの `Accept-CH` レスポンスヘッダーに関係なく、許可ポリシーに応じて、すべてのクライアントリクエストで既定で送信される可能性があります。
 これらのヒントには `Save-Data` (en-US), `Sec-CH-UA` (en-US), `Sec-CH-UA-Mobile` (en-US), `Sec-CH-UA-Platform` (en-US) などがあります。

 高エントロピーヒントは、ユーザーのフィンガープリントに使用される可能性のある、より多くの情報を保持することができるものです。したがって、そのため、提供するかどうかをユーザーエージェントが選択できるような形で制限を設けています。
 その決定はユーザーの環境設定、許可リクエスト、または許可ポリシーに基づいて行われる可能性があります。
 低エントロピーヒントでないすべてのクライアントヒントは、高エントロピーヒントとみなされます。

重要なクライアントヒント
------------

 「重要なクライアントヒント」とは、レスポンスを適用することでレンダリングされるページが大きく変化する可能性があるもので、不快感を与えたりユーザビリティに影響を与える可能性があるため、コンテンツがレンダリングされる前に適用する必要があるものです。
 例えば、`Sec-CH-Prefers-Reduced-Motion` は一般に重要なヒントとして扱われます。なぜなら、アニメーションの動作に著しく影響を与える可能性があり、この環境設定を選んだユーザーはそれを設定する必要があるためです。

 サーバーは `Critical-CH` (en-US) レスポンスヘッダーを `Accept-CH` と共に使用することで、 受け入れられたクライアントヒントが重要なクライアントヒントで もあることを指定することができます（`Critical-CH` のヘッダーは `Accept-CH` にも現れる必要があります）。
 `Critical-CH` のレスポンスを受け取ったユーザーエージェントは、示された Crtical ヘッダーが元のリクエストで送信されたかどうかを調べなければなりません。送信されていなかった場合、ユーザーエージェントはページをレンダリングせずに、リクエストを再試行します。
 この手法は、重要なクライアントヒントを使用して設定されたクライアント環境設定が、たとえ最初のリクエストに含まれていなかったとしても、あるいはサーバーの設定が変更されたとしても、常に使用されることを保証するものです。

例えばこの例では、サーバーは `Accept-CH` によって `Sec-CH-Prefers-Reduced-Motion` を受け入れることをクライアントに指示し、 `Critical-CH` (en-US) は `Sec-CH-Prefers-Reduced-Motion` が重要なクライアントヒントと見なされることを指定するのに使用されます。

```http
HTTP/1.1 200 OK
Content-Type: text/html
Accept-CH: Sec-CH-Prefers-Reduced-Motion
Vary: Sec-CH-Prefers-Reduced-Motion
Critical-CH: Sec-CH-Prefers-Reduced-Motion
```

**メモ:** `Sec-CH-Prefers-Reduced-Motion` も `Vary` ヘッダーに指定することで、ブラウザーに対して、 URL は同じであってもこのヘッダー値に基づいて提供するコンテンツが異なるので、ブラウザーはキャッシュされた既存のレスポンスをそのまま使用せず、このレスポンスを別途キャッシュすべきなのだと示しています。 `Critical-CH` ヘッダーに掲載されている各ヘッダーは `Accept-CH` ヘッダーと `Vary` ヘッダーにも存在しなければなりません。

`Sec-CH-Prefers-Reduced-Motion` は元のリクエストにはなかった重要なヒントなので、クライアントは自動的にリクエストを再試行します。今度は `Sec-CH-Prefers-Reduced-Motion` を通じて、動きの少ないアニメーションを好むユーザーであることをサーバーに指示します。

```http
GET / HTTP/1.1
Host: example.com
Sec-CH-Prefers-Reduced-Motion: "reduce"
```

ヒントの種類
------

### ユーザーエージェントクライアントヒント

 ユーザーエージェント (UA) クライアントヒントヘッダーにより、サーバーはユーザーエージェント（ブラウザー）、オペレーティングシステム、および機器に応じてレスポンスを変化させることができるようになります。
 ヘッダーには `Sec-CH-UA` (en-US), `Sec-CH-UA-Arch` (en-US), `Sec-CH-UA-Bitness` (en-US), `Sec-CH-UA-Full-Version-List` (en-US), `Sec-CH-UA-Full-Version` (en-US), `Sec-CH-UA-Mobile` (en-US), `Sec-CH-UA-Model` (en-US), `Sec-CH-UA-Platform` (en-US), `Sec-CH-UA-Platform-Version` (en-US) などがあります。

クライアントヒントは、ウェブページの JavaScript でユーザーエージェントクライアントヒント API によって使用することができます。

**メモ:** サーバーは現在、 `User-Agent` ヘッダーを解釈することによって、同じ情報のほとんどを取得することができます。
 歴史的な理由から、このヘッダーはほとんど無関係な情報、および特定のユーザーを使用されるかもしれない情報を多く格納しています。
 UA クライアントヒントは、望ましい情報を取得するための、より効率的でプライバシーを維持した方法を提供します。
 最終的にこの古い手法を置き換えることが期待されています。

### ユーザー環境設定メディア特性クライアントヒント

 ユーザー環境設定メディア特性クライアントヒントは、配色や動きの縮小などの CSS メディア特性に対するユーザーエージェントの環境設定に基づいて、サーバーがレスポンスを変更することを可能にします。
 ヘッダーには `Sec-CH-Prefers-Reduced-Motion` (en-US), `Sec-CH-Prefers-Color-Scheme` (en-US) などがあります。

### 端末クライアントヒント

 端末クライアントヒントは、利用できるメモリーや画面のプロパティなど、端末の特性に応じてサーバーがレスポンスを変化させることを可能にします。
 ヘッダーには `Device-Memory`, `DPR`, `Width` (en-US), `Viewport-Width` (en-US) などがあります。

### ネットワーククライアントヒント

 ネットワーククライアントヒントにより、サーバーはユーザーの選択、ネットワーク帯域、レイテンシーに基づいてレスポンスを変化させることができます。
 ヘッダーには `Save-Data` (en-US), `Downlink` (en-US), `ECT` (en-US), `RTT` (en-US) などがあります。

関連情報
----

* クライアントヒントのヘッダー
* `Vary` HTTP ヘッダー
* Client Hints Infrastructure（英語）
* ユーザーエージェントクライアントヒント API
* Improving user privacy and developer experience with User-Agent Client Hints (web.dev)（英語）


プロキシサーバーとトンネリング - HTTP

プロキシサーバーとトンネリング
===============

インターネットのさまざまなネットワークを移動するときに、プロキシサーバーと HTTP トンネルは、 World Wide Web 上のコンテンツへのアクセスを容易にしています。プロキシはユーザーのローカルコンピュータ、またはユーザーのコンピュータとインターネット上の送信先サーバーの間の任意の場所に配置できます。このページではプロキシに関するいくつかの基本を概説し、いくつかの設定オプションを紹介します。

プロキシには、**フォワードプロキシ** (またはトンネルまたはゲートウェイ) と**リバースプロキシ** (負荷分散、認証、復号化またはキャッシュ用のサーバーへのアクセスを制御および保護するために使用される) の 2 種類があります。

フォワードプロキシ
---------

フォワードプロキシ、またはゲートウェイ、または単に「プロキシ」は、クライアントまたはクライアントグループにプロキシサービスを提供します。インターネットには数十万もの公開プロキシが存在する可能性があります。グループによって使用される帯域幅を減らして制御するために、インターネットサービス (DNS や Web ページなど) を格納して転送します。

フォワードプロキシは匿名プロキシにすることもでき、ユーザーは Web をブラウズしたり他のインターネットサービスを使用している間に自分の IP アドレスを隠すことができます。TOR (The Onion Router) は、匿名性のために複数のプロキシを介してインターネットトラフィックをルーティングします。

リバースプロキシ
--------

その名前が示すように、リバースプロキシはフォワードプロキシとは逆の動作を行います。フォワードプロキシはクライアント (またはリクエストホスト) に代わって動作し、リバースプロキシはサーバーに代わって動作します。フォワードプロキシはクライアントの ID を隠すことができますが、リバースプロキシはサーバの ID を隠すことができます。リバースプロキシにはいくつかの利用法がありますが、一部を紹介します。

* ロードバランシング: 複数のウェブサーバーに負荷を分散すること
* 静的なコンテンツのキャッシュ: 写真のような静的コンテンツをキャッシュすることによってウェブサーバーの負荷を軽減すること
* 圧縮: コンテンツを圧縮して最適化し、読み込み時間を短縮すること
プロキシを介してクライアント情報を転送する
---------------------

プロキシは、プロキシの IP アドレスから発信されたようにリクエストを表示させることができます。 これはクライアントの匿名性を提供するためにプロキシを使用する場合に便利ですが、それ以外の場合は元のリクエストの情報が失われます。 元のクライアントの IP アドレスは、デバッグ、統計、またはロケーション依存のコンテンツの生成によく使用されます。 この情報を公開する一般的な方法は、次の HTTP ヘッダーを使用することです。

標準化されたヘッダー:

`Forwarded`

プロキシがリクエストのパスに含まれているときに、変更または失われたクライアント側のプロキシサーバー側からの情報が含まれます。

あるいは事実上の標準バージョン:

`X-Forwarded-For`
Non-standard

HTTP プロキシまたはロードバランサーを介してウェブサーバーに接続しているクライアントの発信元 IP アドレスを識別します。

`X-Forwarded-Host`
Non-standard

クライアントがプロキシまたはロードバランサーへの接続に使用した元のホストを識別します。

`X-Forwarded-Proto`
Non-standard

クライアントがプロキシまたはロードバランサーへの接続に使用したプロトコル (HTTP または HTTPS) を識別します。

(クライアントへの接続ではなく) プロキシ自体に関する情報を提供するには、`Via` ヘッダーを使用できます。

`Via`

プロキシによって、フォワードとリバースの両方のプロキシが追加され、リクエストヘッダーとレスポンスヘッダーに表示されます。

HTTP トンネリング
-----------

トンネリングはデータをカプセル化することによって、パブリックネットワークを介してプライベートネットワークデータおよびプロトコル情報を送信します。 HTTP トンネリングは、より低いレベルのプロトコル (TCP) を伝送するために、より高いレベル (HTTP) のプロトコルを使用しています。

HTTP プロトコルは `CONNECT` と呼ばれるリクエストメソッドを指定します。リクエストされたリソースとの双方向通信を開始し、トンネルを開くために使用することができます。これは、HTTP プロキシの背後にあるクライアントが SSL (つまり HTTPS、443 番ポート) を使用してウェブサイトにアクセスする方法です。ただし、すべてのプロキシサーバーが `CONNECT` メソッドに対応していたり、443 番ポートのみに限定したりしているわけではないことに注意してください。

Wikipedia の HTTP トンネルの記事も参照してください。

プロキシの自動設定 (PAC)
---------------

プロキシ自動設定 (PAC) ファイルは、ウェブブラウザーのリクエスト (HTTP、HTTPS、および FTP) を直接宛先に送信するか、ウェブプロキシサーバーに転送するかを決定する JavaScript 関数です。PAC ファイルに含まれる JavaScript 関数は、次の関数を定義します。

auto-config ファイルは拡張子が `.pac` のファイルに保存する必要があります。
```

proxy.pac
```

MIME タイプは次のように設定されています。
```

application/x-ns-proxy-autoconfig
```

このファイルは `FindProxyForURL` という関数で構成されています。以下の例は、内部 DNS サーバーが内部ホスト名のみを解決できるように設定されている環境で動作し、解決できないホストに対してのみプロキシを使用することを目標としています。

```js
function FindProxyForURL(url, host) {
  if (isResolvable(host)) return "DIRECT";
  else return "PROXY proxy.mydomain.com:8080";
}
```

他の例についてはプロキシ自動設定 (PAC) を参照してください。

関連情報
----

* `CONNECT`
* Proxy server on Wikipedia


HTTP メッセージ - HTTP

HTTP メッセージ
==========

HTTP メッセージは、サーバーとクライアントがデータを交換する手段です。クライアントが送信してサーバーにアクションを起こさせる*リクエスト*と、サーバーの回答である*レスポンス*の、2 種類のメッセージがあります。

HTTP メッセージは ASCII でエンコードされたテキスト情報で構成されており、複数の行にまたがります。HTTP/1.1 およびそれより前のバージョンのプロトコルでは、メッセージがコネクション内でそのまま送信されます。HTTP/2 では、人間が読める形式のメッセージを HTTP フレームに分割して、最適化やパフォーマンスの向上を実現します。

ウェブ開発者やウェブ管理者がこれらテキスト形式の HTTP メッセージを作成することはめったにありません。ウェブブラウザー、プロキシー、ウェブサーバーといったソフトウェアが行います。それらは HTTP メッセージを設定ファイル（プロキシーやサーバー）、API （ブラウザー）、あるいは他のインターフェイスによって提供します。

![ユーザーやスクリプトやサーバーが生成したイベントから、 HTTP/1.x メッセージが生成され、 HTTP/2 を使用している場合は、 HTTP/2 ストリームにバイナリーフレーム化され、送信されます。](/ja/docs/Web/HTTP/Messages/httpmsg2.png)

HTTP/2 のバイナリーフレーム化方式は、適用される API や設定ファイルの変更を必要としないように設計されています。これはユーザーに対して透過的です。

HTTP のリクエストやレスポンスは似た構造を共用しており、以下の要素で構成されます。

1. 実行するリクエスト、または成功か失敗かの状態を表す*開始行*。開始行は常に 1 行です。
2. リクエストの詳細を示す、またはメッセージに含まれる本体を説明する、省略可能な *HTTP ヘッダー*一式。
3. リクエストのメタ情報がすべて送信されたことを示す空行。
4. リクエストに関連付けられたデータ (HTML フォームの内容など)、あるいはレスポンスに関連付けられたドキュメントを含む、省略可能な*本体*。本体が存在することやそのサイズは、開始行や HTTP ヘッダーで指定します。

HTTP メッセージの開始行と HTTP ヘッダーは、まとめてリクエストの*ヘッド*として知られています。一方、ペイロードは*本体*として知られています。

![リクエストとレスポンスは HTTP で共通の構造を持っています。](/ja/docs/Web/HTTP/Messages/httpmsgstructure2.png)

HTTP リクエスト
----------

### リクエスト行

*メモ: HTTP リクエストにおいて、開始行は『リクエスト行』と呼ばれます。*

HTTP リクエストは、アクションを始めるためにクラアントからサーバーへ送られます。そのリクエスト行には、3 つの要素が含まれています。

1. *HTTP メソッド*。実行するアクションを表わす動詞 (`GET`、`PUT`、`POST` など) または名詞 (`HEAD`、`OPTIONS`)。例えば `GET` はリソースを取り込むこと、`POST` はデータをサーバーへ送信すること (リソースを作成または変更する、あるいは返送する一時的なドキュメントを生成する) ことを示します。
2. *リクエスト対象*。通常は URL ですが、プロトコル、ポート番号、ドメインの絶対パスは通常、リクエストの状況から明らかにされます。リクエスト対象の形式は、HTTP メソッドにより異なります。以下のような形式があります。
    * 最後に `'?'` とクエリー文字列がある絶対パス。これは*オリジン形式*とも呼ばれているもっとも一般的な形式であり、`GET`、`POST`、`HEAD`、`OPTIONS` メソッドで使用します。
        + `POST / HTTP/1.1`
        + `GET /background.png HTTP/1.0`
        + `HEAD /test.html?query=alibaba HTTP/1.1`
        + `OPTIONS /anypage.html HTTP/1.0`
    * 完全な URL は*絶対形式*とも呼ばれ、主にプロキシーへ接続する際に `GET` で使用します。
     `GET https://developer.mozilla.org/ja/docs/Web/HTTP/Messages HTTP/1.1`
    * ドメイン名とポート（省略可能。`':'` を前につける）で構成される、URL の authority の部分は*認証形式*と呼ばれます。これは `CONNECT` で HTTP トンネルを設定するときに限り使用されます。
     `CONNECT developer.mozilla.org:80 HTTP/1.1`
    * 単純なアスタリスク (`'*'`) である*アスタリスク形式*は `OPTIONS` で使用され、サーバー全体を表します。
     `OPTIONS * HTTP/1.1`
3. *HTTP バージョン*。これはメッセージの残りの部分の構造を定義しており、レスポンスで使用することを想定しているバージョンを示す役割もあります。
### ヘッダー

リクエストの HTTP ヘッダー は、HTTP ヘッダーの一定の基本構造に従います。大文字・小文字を区別しない文字列の後にコロン (`':'`) と、ヘッダーに応じた構造の値が続きます。値を含むヘッダー全体は 1 行で構成されており、とても長くなる場合もあります。

様々なヘッダーがリクエストに現れることがあります。これらはいくつかのグループに分類されます。

* 一般ヘッダーは、 `Via` など、メッセージ全体に適用されるものです。
* リクエストヘッダーは、 `User-Agent`, `Accept` などで、指定するとリクエストを変更するもの（`Accept-Language` など）、状況を示すもの（`Referer` など）、条件を制約するもの（`If-None` など）があります。
* 表現ヘッダーは `Content-Type` など、メッセージデータの下の形式や適用されているエンコーディングを説明します（メッセージの本体がある場合のみ存在します）。

![HTTP リクエストのヘッダーの例](/ja/docs/Web/HTTP/Messages/http_request_headers3.png)

### 本体

リクエストの最後の部分が本体 (body) です。本体が存在しないリクエストもあります。リソースを取り込むリクエストである `GET`, `HEAD`, `DELETE`, `OPTIONS` は通常、本体は不要です。サーバー内のデータを更新するためにデータを送信するリクエストもあり、 `POST` リクエストでよくあります（HTML フォームのデータを持つ）。

本体は、大きく 2 種類に分類されます。

* 単一リソースの本体。1 個のファイルで構成され、`Content-Type` と `Content-Length` の 2 つのヘッダーで定義されます。
* 複数リソースの本体。マルチパートの本体で構成され、それぞれが異なる情報を持ちます。これは主に、 HTML フォームと関連付けられます。
HTTP レスポンス
----------

### ステータス行

HTTP レスポンスの開始行は*ステータス行*と呼ばれ、以下の情報を持ちます。

1. *プロトコルバージョン*。通常 `HTTP/1.1` です。
2. *ステータスコード*。リクエストが成功したか失敗したかを示します。一般的なステータスコードは `200`, `404`, `302` です。
3. *ステータステキスト*。手短な単なる情報ですが、人間が HTTP メッセージを理解するのを助けるために、ステータスコードをテキストで説明します。

一般的に、ステータス行は `HTTP/1.1 404 Not Found.` のようになります。

### ヘッダー

レスポンスの HTTP ヘッダーは、他のヘッダーと同様に一定の基本構造に従います。大文字・小文字を区別しない文字列の後にコロン (`':'`) と、ヘッダーの種類に応じた構造の値が続きます。値を含むヘッダー全体は 1 行で構成されます。

使用できるレスポンスヘッダーは多数あります。これらはいくつかのグループに分類されます。

* 一般ヘッダーは `Via` など、メッセージ全体に適用されるものです。
* レスポンスヘッダーは `Vary` や `Accept-Ranges` など、ステータス行で伝えられないサーバーの追加情報を与えます。
* 表現ヘッダーは `Content-Type` など、レスポンスの本体に適用されます。通常、レスポンス内に本体がない場合はこのようなヘッダーは送信されません。

![HTTP レスポンスヘッダーの例](/ja/docs/Web/HTTP/Messages/http_response_headers2.png)

### 本体

レスポンスの最後の部分が本体です。本体を持たないレスポンスもあります。 `201` **`Created`** や `204` **`No Content`** といったステータスコードのレスポンスは通常、本体がありません。

本体は、大きく 3 種類に分類されます。

* 大きさが判明している 1 個のファイルで構成される、単一リソースの本体。 `Content-Type` と `Content-Length` の 2 つのヘッダーで定義されます。
* 大きさが不明な 1 個のファイルで構成される、単一リソースの本体。 `Transfer-Encoding` を `chunked` に設定して、 chunked 形式でエンコードされます。
* 複数リソースの本体。マルチパートの本体で構成され、それぞれが異なる情報のセクションを持ちます。これは比較的まれです。
HTTP/2 フレーム
-----------

HTTP/1.x のメッセージには、パフォーマンスの欠点があります。

* ヘッダーは本体と異なり、圧縮されません。
* あるメッセージと次のメッセージでヘッダーが酷似していることがよくありますが、それでも複数のコネクションにわたって繰り返されます。
* 多重化することができません。同じサーバーに対して複数のコネクションを開かなければなりません。また、ウォーム状態の TCP コネクションはコールド状態のコネクションより効率的です。

HTTP/2 は次の段階に進みました。 HTTP/1.x のメッセージを、ストリーム内に埋め込まれるフレームに分割します。データのフレームとヘッダーのフレームは区別され、ヘッダーの圧縮が可能になります。*多重化*と呼ばれる処理によって複数のストリームがまとめられ、下層の TCP コネクションの効率を向上させることができます。

![HTTP/2 は HTTP メッセージをフレーム（単一のストリームの一部）に分割するように変更し、より最適化できるようにします。](/ja/docs/Web/HTTP/Messages/binary_framing2.png)

HTTP フレームは、ウェブ開発者に対しては透過的になります。これは HTTP/2 において、 HTTP/1.1 メッセージと基盤となるトランスポート層との間のさらなるステップです。 HTTP フレームを利用するためにウェブ開発者が使用する API を変更する必要はありません。ブラウザーとサーバーの両方で利用可能になれば、 HTTP/2 が有効になり使用されます。

まとめ
---

HTTP メッセージは、 HTTP を使用する際に重要なものです。その構造はシンプルであり、拡張性が高くなっています。 HTTP/2 のフレーム化機能は、 HTTP/1.x の構文と基盤となるトランスポートプロトコルの間の新たな中間層であり、根底は変わりません。実証された仕組みの上に構築されました。