aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/http/headers/cache-control/index.md
blob: b7b407fc0724387190d6bdb92c24f7812dd82dd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
---
title: Cache-Control
slug: Web/HTTP/Headers/Cache-Control
tags:
  - Cache-Control
  - HTTP
  - HTTP ヘッダー
  - リクエストヘッダー
  - レスポンスヘッダー
  - リファレンス
browser-compat: http.headers.Cache-Control
translation_of: Web/HTTP/Headers/Cache-Control
---

{{HTTPSidebar}}

**`Cache-Control`** は HTTP のヘッダーフィールドで、 [キャッシュ](/ja/docs/Web/HTTP/Caching) をブラウザーや共有キャッシュ(プロキシーや CDN など)において制御するためのディレクティブ (指示) を、リクエストとレスポンスの両方で保持します。

<table class="properties">
  <tbody>
    <tr>
      <th scope="row">ヘッダー種別</th>
      <td>
        {{Glossary("Request header", "リクエストヘッダー")}},
        {{Glossary("Response header", "レスポンスヘッダー")}}
      </td>
    </tr>
    <tr>
      <th scope="row">{{Glossary("Forbidden header name", "禁止ヘッダー名")}}</th>
      <td>いいえ</td>
    </tr>
    <tr>
      <th scope="row">
        {{Glossary("CORS-safelisted response header", "CORS セーフリストレスポンスヘッダー")}}
      </th>
      <td>はい</td>
    </tr>
  </tbody>
</table>

## 構文

キャッシュのディレクティブには、以下のような規則があります。

- 大文字と小文字は区別されませんが、実装によっては大文字のディレクティブを認識しないものもあるので、小文字を推奨します。
- 複数のディレクティブはカンマで区切ります。
- いくつかのディレクティブにはオプションの引数があります。

### キャッシュディレクティブ

標準的な `Cache-Control` ディレクティブは以下のように定義されています。

| リクエスト       | レスポンス               |
| :--------------- | :----------------------- |
| `max-age`        | `max-age`                |
| `max-stale`      | -                        |
| `min-fresh`      | -                        |
| -                | `s-maxage`               |
| `no-cache`       | `no-cache`               |
| `no-store`       | `no-store`               |
| `no-transform`   | `no-transform`           |
| `only-if-cached` | -                        |
| -                | `must-revalidate`        |
| -                | `proxy-revalidate`       |
| -                | `must-understand`        |
| -                | `private`                |
| -                | `public`                 |
| -                | `immutable`              |
| -                | `stale-while-revalidate` |
| `stale-if-error` | `stale-if-error`         |

注意: [互換性一覧表](#ブラウザーの互換性)で対応状況を確認してください。解釈できないユーザーエージェントはこれらを無視します。

## 用語集

このドキュメントでは、次の用語が使用されています。すべてではありませんが、仕様書に基づいています。

- `(HTTP) キャッシュ`
  - : リクエストとレスポンスを保持し、次のリクエストで再利用するための実装。共有キャッシュまたはプライベートキャッシュのいずれかです。
- `共有キャッシュ`
  - : オリジンサーバーとクライアントの間に存在するキャッシュ (Proxy, CDN など)。1 つのレスポンスを保存し、それを複数のユーザーで再利用します。したがって、開発者は共有キャッシュにパーソナライズされたコンテンツをキャッシュとして保存することは避けるべきです。
- `プライベートキャッシュ`
  - : クライアント内に存在するキャッシュです。*ローカルキャッシュ*、あるいは単に*ブラウザーキャッシュ*などとも呼ばれます。ユーザーのためにパーソナライズされたコンテンツを保存し、再利用できます。
- `レスポンスの格納`
  - : キャッシュ可能な場合には、レスポンスをキャッシュに保存します。しかし、そのまま再利用されるとは限りません。(通常、「キャッシュ」はレスポンスを保存することを意味します。)
- `レスポンスの再利用`
  - : キャッシュされたレスポンスを次のリクエストに再利用します。
- `レスポンスの再検証`
  - : オリジンサーバーに、保存されているレスポンスがまだ新しいか確認します。通常は条件付きのリクエストで行います。
- `新鮮なレスポンス`
  - : レスポンスが新しい状態であることを示します。これは通常、リクエストの指示に応じて、レスポンスを後続のリクエストに再利用できることを意味します。
- `古いレスポンス`
  - : レスポンスが古い状態になっていることを示します。これは通常、レスポンスがそのままでは再利用できないことを意味します。キャッシュストレージは古いレスポンスをすぐに削除する必要はありません。なぜなら、再検証によってレスポンスが古いものから再び新しい状態に変わる可能性があるからです。
- `Age`
  - : レスポンスが生成されてからの経過時間です。レスポンスが新しい状態か古い状態かの基準となります。

## ディレクティブ

このセクションでは、キャッシュに影響を与えるディレクティブ(レスポンスディレクティブとリクエストディレクティブの両方)を列挙します。

### レスポンスディレクティブ

#### `max-age`

レスポンスディレクティブの`max-age=N` は、レスポンスが生成されてから _N_ 秒後まで、レスポンスが新鮮なままであることを示します。

```
Cache-Control: max-age=604800
```

キャッシュがこのリクエストを保存し、新鮮なうちに後続のリクエストに再利用できることを示します。

なお、`max-age` はレスポンスを受信してからの経過時間ではなく、オリジンサーバーでレスポンスが生成されてからの経過時間であることに注意してください。したがって、他のキャッシュ(レスポンスが通ったネットワーク経路上)が 100 秒間保存した場合(レスポンスヘッダーフィールドの `Age` で示される)、ブラウザーキャッシュはその鮮度の有効期間から 100 秒を差し引きます。

```
Cache-Control: max-age=604800
Age: 100
```

#### `s-maxage`

レスポンスディレクティブの `s-maxage` も、レスポンスが新鮮である期間を示します(`max-age` に似ています)。しかし、これは共有キャッシュ特有のもので、共有キャッシュは `s-maxage``max-age` の両方が存在した場合 `max-age` を無視します。

```
Cache-Control: s-maxage=604800
```

#### `no-cache`

レスポンスディレクティブの `no-cache` は、キャッシュに保存できることを示しますが、キャッシュがオリジンサーバーから切断された場合でも、再利用の前にオリジンサーバーで検証しなければなりません。

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

キャッシュに、保存されているコンテンツを再利用する際に、必ず更新がないかどうかをチェックさせたい場合は、 `no-cache` を使用する必要があります。これは、キャッシュがオリジンサーバーに各リクエストを再検証することを要求することで実現されます。

`no-cache` はキャッシュにレスポンスを保存することを許可しますが、再利用する前に再検証することを要求します。もし、「キャッシュさせない」の意味が実際には「保存させない」であるなら、`no-store` が使用すべきディレクティブです。

#### `must-revalidate`

レスポンスディレクティブの `must-revalidate` は、レスポンスがキャッシュに保存され、新鮮なうちは再利用できることを示します。古くなったレスポンスは、再利用する前にオリジンサーバーで検証されなければなりません。

通常、`must-revalidate` は `max-age` と共に使用されます。

```
Cache-Control: max-age=604800, must-revalidate
```

HTTP では、キャッシュがオリジンサーバーから切り離されたときに、古いレスポンスを再利用できます。`must-revalidate` はそれを防ぐための方法で、キャッシュは保存されたレスポンスを元のサーバーで再検証するか、それが検証不可能な場合は 504 (Gateway Timeout) のレスポンスを生成します。

#### `proxy-revalidate`

レスポンスディレクティブの `proxy-revalidate``must-revalidate` と同等ですが、共有キャッシュにのみ適用されます。

#### `no-store`

レスポンスディレクティブの `no-store` は、あらゆる種類のキャッシュが(プライベートであろうと共有であろうと)このレスポンスを保存しないようにすることを指示します。

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

#### `private`

レスポンスディレクティブの `private` は、レスポンスがプライベートキャッシュ(ブラウザーのローカルキャッシュなど)にのみ保存できることを示します。

```
Cache-Control: private
```

ユーザー個人を特定するコンテンツ、特にログイン後に受け取るレスポンスや、Cookie で管理されるセッションについては、`private` ディレクティブを追加する必要があります。

パーソナライズされたコンテンツを持つレスポンスに `private` を付け忘れると、そのレスポンスが共有キャッシュに保存され、複数のユーザーによって再利用されてしまい、個人情報の漏えいに繋がる可能性があります。

#### `public`

ヘッダーフィールドに `Authorization` を持つリクエストに対するレスポンスは、共有キャッシュに保存してはいけません。しかし、`public` ディレクティブはそのようなレスポンスを共有キャッシュに保存します。

```
Cache-Control: public
```

一般に、ページが Basic 認証または Digest 認証で制御されている場合、ブラウザーは `Authorization` ヘッダーを付けてリクエストを送信します。つまり、レスポンスは制限されたユーザー(アカウントを持つユーザー)のみにアクセス制御され、たとえ `max-age` がついていても基本的に共有キャッシュに保存可能ではありません。

その制限を解除するために `public` ディレクティブが使用できます。

```
Cache-Control: public, max-age=604800
```

なお、`s-maxage` や `must-revalidate` もこの制限を解除します。

リクエストに `Authorization` ヘッダーがない場合、あるいはレスポンスに ` s-maxage` または `must-revalidate` をすでに使用している場合は、` public` を使用する必要はありません。

#### `must-understand`

レスポンスディレクティブの `must-understand` は、ステータスコードに基づいてキャッシュの要件を理解している場合にのみ、キャッシュがレスポンスを保存すべきであると示します。

`must-understand` は、フォールバック動作のために `no-store` と組み合わせる必要があります。

```
Cache-Control: must-understand, no-store
```

キャッシュが `must-understand` に対応していない場合は、無視されます。`no-store` も存在する場合は、レスポンスは保存されません。

キャッシュが `must-understand` に対応している場合、ステータスコードに基づいてキャッシュの要件を理解してレスポンスを保存します。

#### `no-transform`

仲介者 (intermedialies) の中には、さまざまな理由でコンテンツを変換するものがあります。たとえば、転送サイズを小さくするために画像を変換するものなどです。場合によっては、これはコンテンツプロバイダーにとって望ましくありません。

`no-transform` は、仲介者が(キャッシュを実装しているかどうかに関係なく)レスポンスの内容を変換すべきではないことを示します。

注意: [Google’s Web Light](https://support.google.com/webmasters/answer/6211428) は、そのような仲介者の一種です。これは、キャッシュストアや低速接続のデータを最小化するために画像を変換し、オプトアウトオプションとして `no-transform` に対応します。

#### `immutable`

レスポンスディレクティブの `immutable` は、レスポンスが新鮮な間は更新されないことを示します。

```
Cache-Control: public, max-age=604800, immutable
```

静的なリソースに対する最近のベストプラクティスは、バージョン/ハッシュを URL に含める一方で、リソースには決して手を加えず必要なときに、新しいバージョン番号/ハッシュを持つ新しいバージョンでリソースを更新し、URL も異なるものにすることです。これを **cache-busting** パターンと呼びます。

```
<script src=https://example.com/react.0.0.0.js></script>
```

ユーザーがブラウザーをリロードすると、ブラウザーはオリジンサーバーに検証のための条件付きリクエストを送信します。しかし、これらの静的リソースは、ユーザーがブラウザーをリロードしても決して変更されないため、再検証する必要がありません。
`immutable` はキャッシュにレスポンスが新鮮な間は不変であることを伝え、サーバーへの不要な条件付きリクエストを回避します。

リソースに cache-busting パターンを使用し、長い `max-age` を適用すると、再検証を避けるために `immutable` も追加することができます。

#### `stale-while-revalidate`

レスポンスディレクティブの `stale-while-revalidate` は、キャッシュを再検証している間、古いレスポンスの再利用が可能なことを示します。

```
Cache-Control: max-age=604800, stale-while-revalidate=86400
```

上記の例では、レスポンスは 7 日間(604800 秒間)は新鮮です。7 日後、レスポンスは古くなりますが、キャッシュは翌日(86400 秒後)のリクエストに再利用できます。ただし、バックグラウンドでレスポンスを再検証することが条件です。

再検証により、キャッシュは再び新鮮になるため、クライアントはその期間中は常に新鮮であったかのように見えます。これにより再検証の遅延ペナルティを効果的にクライアントから隠蔽できます。

その間にリクエストがなければ、キャッシュは古くなり、次のリクエストは正常に再検証されます。

#### `stale-if-error`

レスポンスディレクティブの `stale-if-error` は、オリジンサーバーがエラー(500、502、503、504)でレスポンスを返したときに、キャッシュが古いレスポンスを再利用できることを指示します。

```
Cache-Control: max-age=604800, stale-if-error=86400
```

上記の例では、レスポンスは 7 日間(604800 秒間)は新鮮です。7 日を過ぎると古くなりますが、サーバーがエラーでレスポンスを返した場合はさらに 1 日(86400 秒間)利用できます。

一定時間経過後、保存されたレスポンスは通常通り古くなります。つまり、オリジンサーバーがエラーレスポンスを送信した場合、クライアントはそのままエラーレスポンスを受信します。

## リクエストディレクティブ

### `no-cache`

リクエストディレクティブの `no-cache` はキャッシュに、再利用する前にオリジンサーバーでレスポンスを検証するように要求します。

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

`no-cache` は、キャッシュに新しいレスポンスがある場合でも、クライアントが最新のレスポンスを要求することを可能にします。

ブラウザーは通常、ユーザーがページを**強制再読み込み**したときに、リクエストに `no-cache` を追加します。

### `no-store`

リクエストディレクティブの `no-store` は、オリジンサーバーのレスポンスが保存される可能性がある場合でも、クライアントがリクエストと対応するレスポンスを保存しないようにキャッシュに要求することを可能にします。

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

主要なブラウザーは `no-store` を使ったリクエストに対応していないことに注意してください。

### `max-age`

リクエストディレクティブの `max-age=N` は、オリジンサーバーで _N_ 秒以内に生成された、保存済みレスポンスをクライアントが許可することを示します。

```
Cache-Control: max-age=3600
```

上記の場合、`Cache-Control: max-age=604800` のレスポンスが 3 時間前にキャッシュに保存されていた場合、キャッシュはそのレスポンスを再利用できません。

以下で説明するように、多くのブラウザーは**再読み込み**時に、このディレクティブを使用します。

```
Cache-Control: max-age=0
```

`max-age=0``no-cache` の回避策です。多くの古い (HTTP/1.0 の) キャッシュの実装は `no-cache` に対応していないからです。最近のブラウザーは、後方互換性のために `max-age=0` を「再読み込み」の際に使用し、`no-cache` を使用して「強制再読み込み」を行うようになっています。

### `max-stale`

リクエストディレクティブの `max-stale=N` は、クライアントが *N* 秒以内に失効した保存されたレスポンスを許可することを示します。

```
Cache-Control: max-stale=3600
```

上記の場合、3 時間前に `Cache-Control: max-age=604800` を持つレスポンスがキャッシュに保存されていた場合、キャッシュはそのレスポンスを再利用できません。

クライアントは、オリジンサーバーがダウンしているときや遅すぎるときにこのヘッダーを使うことができ、多少古くてもキャッシュされたレスポンスをキャッシュから受け入れることができます。

主要なブラウザーは `max-stale` を指定したリクエストに対応していないことに注意してください。

### `min-fresh`

リクエストディレクティブの `min-fresh` は、クライアントが少なくとも _N_ 秒間新鮮な保存されたレスポンスを許可することを示します。

```
Cache-Control: min-fresh=600
```

上記の場合、51 分前に `Cache-Control: max-age=3600` を持つレスポンスがキャッシュに保存されていた場合、キャッシュはそのレスポンスを再利用できません。

クライアントがこのヘッダーを使用できるのは、ユーザーのレスポンスが新鮮であることだけでなく、一定期間更新されないことも要求する場合です。

主要なブラウザーは `min-fresh` を使ったリクエストに対応していないことに注意してください。

### `no-transform`

レスポンスの `no-transform` と同じ意味ですが、リクエストに対するものです。

### `only-if-cached`

クライアントは、キャッシュがすでに保存済みのレスポンスを転送する必要があることを示します。キャッシュにレスポンスが保存されている場合、それが再利用されます。

## 利用例

### 格納を防止

レスポンスをキャッシュに保存したくない場合は、 `no-store` ディレクティブを使用します。

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

`no-cache` は「保存することはできるが、検証する前に再利用しない」という意味なので、レスポンスが保存されないようにするためのものではないことに注意してください。

```plain example-bad
Cache-Control: no-cache
```

理論的には、ディレクティブが衝突した場合、最も制限の厳しいディレクティブが尊重されるべきです。つまり、以下の例は基本的に無意味です。`private`, `no-cache`, `max-age=0`, `must-revalidate``no-store` と競合しているからです。

```plain example-bad
# 競合
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate

# 以下のものと等しい
Cache-Control: no-store
```

### “cache busting” における静的資産のキャッシュ

バージョン/ハッシュビルドを持つ静的資産を構築する場合、ファイル名やクエリー文字列にバージョン/ハッシュを追加することは、キャッシュを管理するための良い方法です。

例:

```html
<!-- index.html -->
<script src=/assets/react.min.js></script>
<img src=/assets/hero.png width=900 height=400>
```

React ライブラリーのバージョンは、ライブラリーを更新すると変わりますし、`hero.png` も画像を編集すると変わります。そのため、これらは `max-age` を使ってキャッシュに保存するのは難しくなります。

このような場合、特定の番号のついたバージョンのライブラリーを使用し、画像の URL にハッシュを含めることでキャッシュの要求を満たすことができます。

```html
<!-- index.html -->
<script src=/assets/react.0.0.0min.js></script>
<img src=/assets/hero.png?hash=deadbeef width=900 height=400>
```

コンテンツは決して変更されないので、 `max-age` を長い値や `immutable` にすることができます。

```
# /assets/*
Cache-Control: max-age=31536000, immutable
```

ライブラリーを更新したり、画像を編集したりすると、新しいコンテンツは新しい URL を持つはずなので、キャッシュは再利用されません。それを “cache busting” パターンと呼びます。

`no-cache` を使用して HTML レスポンス自体がキャッシュされないようにしてください。 `no-cache` では再検証することができるので、クライアントが HTML レスポンスや静的資産の新しいバージョンを正しく受信します。

```
# /index.html
Cache-Control: no-cache
```

注意: `index.html` が Basic 認証または Digest 認証で制御されている場合、`/assets` 以下のファイルは共有キャッシュに保存されません。もし `/assets/` のファイルが共有キャッシュに保存するのに適しているなら、 `public``s-maxage` または `must-revalidate` のうちの 1 つが必要です。

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

動的に生成されるコンテンツや、静的であっても頻繁に更新されるコンテンツでは、ユーザーが常に最新版を受信できるようにしたいものです。

もし、レスポンスがキャッシュされることを意図していないからといって `Cache-Control` ヘッダーを追加しなければ、予期せぬ結果を引き起こす可能性があります。キャッシュストレージは、推測でキャッシュすることが許されています。したがって、キャッシュに関する何らかの要求がある場合は、常に `Cache-Control` ヘッダーで明示的に示す必要があります。

レスポンスに `no-cache` を追加すると、サーバーで再検証が行われるので、毎回新鮮なレスポンスを提供できます。また、クライアントがすでに新しいレスポンスを持っている場合は、`304 Not Modified` とだけレスポンスを返します。

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

ほとんどの HTTP/1.0 キャッシュは `no-cache` ディレクティブに対応していないので、歴史的には `max-age=0` が回避策として使用されてきました。しかし、`max-age=0` だけでは、キャッシュがオリジンサーバーから切断されたときに、古いレスポンスが再利用される可能性がありました。`must-revalidate` はそれに対応するものです。そのため、以下の例では `no-cache` と同等になっています。

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

しかし、今のところ、単に `no-cache` を代わりに使用できます。

### 既に格納されたキャッシュのクリア

残念ながら、すでに保存されているレスポンスをキャッシュからクリアするためのキャッシュディレクティブはありません。

クライアントやキャッシュが、あるパスに対する新鮮なレスポンスを保存しており、サーバーへリクエストを送信しない状態を想像してください。そのパスに対してサーバーができることは何もありません。

代替として `Clear-Site-Data` はブラウザーのキャッシュをクリアできます。しかし、これはあるサイトの保存されたすべてのレスポンスをクリアするので注意してください。そして、クリアされるのはブラウザー内のキャッシュのみで、共有キャッシュはクリアされません。

## 仕様書

{{Specifications}}

## ブラウザーの互換性

{{Compat}}

[HTTP Caching](https://httpwg.org/http-core/draft-ietf-httpbis-cache-latest.html)
[RFC5861 - HTTP Cache-Control Extensions for Stale Content](https://datatracker.ietf.org/doc/html/rfc5861)
[RFC8246 - HTTP Immutable Responses](https://datatracker.ietf.org/doc/html/rfc8246)

## 関連情報

- [HTTP キャッシュの FAQ](/ja/docs/Web/HTTP/Caching)
- [Caching Tutorial for Web Authors and Webmasters](https://www.mnot.net/cache_docs/)
- [Caching best practices & max-age gotchas](https://jakearchibald.com/2016/caching-best-practices/)
- [Cache-Control for Civilians](https://csswizardry.com/2019/03/cache-control-for-civilians/)
- {{HTTPHeader("Age")}}
- {{HTTPHeader("Expires")}}
- {{HTTPHeader("Pragma")}}