ステータスコードごとの Edge Cache TTL
Cloudflare では、ステータスコードごとの Edge Cache TTL を設定できます。
デフォルトでは、Cloudflare は cache-control ディレクティブや expires レスポンスヘッダが存在しない場合、特定の HTTP レスポンスコードを以下の Edge Cache TTL でキャッシュします。
HTTP status code Default TTL 200, 206, 301 120m 302, 303 20m 404, 410 3m 403 0s 500, 502, 503, 504 0s
Default TTL = 0s の場合は、デフォルトではリソースをキャッシュしない形になります。
Cloudflareは、Edge Cache TTLページルールがヘッダを上書きしない限り、オリジンウェブサーバのキャッシュヘッダを以下の順序で尊重します。
Cloudflareは以下の場合、リソースをキャッシュしません:
Cache-Control ヘッダが private、no-store、no-cache、または max-age=0 に設定されている場合。
オリジンの準備
以下の要領でオリジンサーバーを準備します。
その上で特定のステータスコードを返す HTML ページを用意します。
<?php http_response_code(400); ?>
<!DOCTYPE html>
<html>
<head>
<title>php-generated 400</title>
</head>
<body>
This is a 400 error page.
</body>
</html>
.html
をキャッシュする設定
HTML はデフォルトでキャッシュされないため、Cache Rules を使ってキャッシュする設定にしておきます。
- When incoming requests match…
(http.request.uri.path.extension eq "html")
Status code TTL 設定
デフォルト設定から変更したい場合、Cache Rules を使って、例えば以下のように設定できます。
400 で確認
while true; do curl -sIXGET https://example.com/400.html | grep -e cf-cache-status: -e age: -e HTTP -e cache-control: && sleep 3; done
デフォルト = 0s
HTTP/2 400
cf-cache-status: MISS
HTTP/2 400
cf-cache-status: MISS
HTTP/2 400
cf-cache-status: MISS
Status code TTL = 30s
Status code TTL 設定が反映されたことがわかります。
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: EXPIRED
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 3
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 6
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 3
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 9
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 12
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 25
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: EXPIRED
HTTP/2 400
cache-control: max-age=31536000
cf-cache-status: HIT
age: 6
403 で確認
while true; do curl -sIXGET https://example.com/403.html | grep -e cf-cache-status: -e age: -e HTTP -e cache-control: && sleep 3; done
(.htaccess
などのパスを使って確認するのもありです。)
デフォルト = 0s
HTTP/2 403
cf-cache-status: MISS
HTTP/2 403
cf-cache-status: MISS
HTTP/2 403
cf-cache-status: MISS
Status code TTL = 30s
Status code TTL 設定が反映されたことがわかります。
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: MISS
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 3
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 6
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 9
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 12
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 15
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 21
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 24
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 28
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: EXPIRED
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
HTTP/2 403
cache-control: max-age=31536000
cf-cache-status: HIT
age: 6
404 で確認
while true; do curl -sIXGET https://example.com/404.html | grep -e cf-cache-status: -e age: -e HTTP -e cache-control: && sleep 3; done
(実際には存在しないパスを使って確認するのもありです。)
デフォルト = 180s
HTTP/2 404
cf-cache-status: MISS
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: HIT
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: HIT
age: 7
cache-control: public, max-age=14400
...
HTTP/2 404
cf-cache-status: HIT
age: 174
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: EXPIRED
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: HIT
age: 174
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: HIT
age: 9
cache-control: public, max-age=14400
HTTP/2 404
cf-cache-status: HIT
age: 10
cache-control: public, max-age=14400
Status code TTL = -1 (no store)
Status code TTL 設定が反映されたことがわかります。
HTTP/2 404
cache-control: public, max-age=31536000
cf-cache-status: MISS
HTTP/2 404
cache-control: public, max-age=31536000
cf-cache-status: MISS
HTTP/2 404
cache-control: public, max-age=31536000
cf-cache-status: MISS
502 で確認
while true; do curl -sIXGET https://example.com/502.html | grep -e cf-cache-status: -e age: -e HTTP -e cache-control: && sleep 3; done
デフォルト = 0s
HTTP/2 502
cf-cache-status: MISS
HTTP/2 502
cf-cache-status: MISS
HTTP/2 502
cf-cache-status: MISS
Status code TTL = 1s
STALE
状態で返してしまいます。
HTTP/2 502
cache-control: max-age=31536000
cf-cache-status: MISS
HTTP/2 502
cache-control: public, max-age=0
cf-cache-status: STALE
age: 3
HTTP/2 502
cache-control: public, max-age=0
cf-cache-status: STALE
age: 6
HTTP/2 502
cache-control: max-age=31536000
cf-cache-status: STALE
HTTP/2 502
cache-control: public, max-age=0
cf-cache-status: STALE
age: 12
Amazon CloudFront の場合、以下のような挙動がドキュメントで公開されていますが、Cloudflare でも同様の挙動となっています。
- コンテンツがキャッシュに保持される期間 (有効期限) の管理 - Amazon CloudFront
オリジンが接続不能で、さらに最小 TTL が 0 より大きい場合、CloudFront は、先にオリジンから取得済みのオブジェクトを返信します。この動作を回避するには、Cache-Control: stale-if-error=0 ディレクティブに、オリジンから返されたオブジェクトを含めます。このようにすることで、オリジンが接続不能な場合に CloudFront が以後のリクエストに応答する際、以前にオリジンから取得したオブジェクトを返すのではなくエラーを返すようになります。
- Origin Cache Control · Cloudflare Cache (CDN) docs
stale-if-error=seconds
— Indicates that when an error is encountered, a cached stale response may be used to satisfy the request, regardless of other freshness information. To avoid this behavior, includestale-if-error=0
directive with the object returned from the origin.
Status code TTL = 1s + stale-if-error=0
stale-if-error
ディレクティブを使うことで、オリジンがエラーステータス(ステータスコード 500, 502, 503, 504)を応答する場合に一定期間は古いキャッシュを使用できますが、 STALE
を使用したくない場合にはオリジン側で stale-if-error=0
を明示的に追加して無効化することで意図した通りの挙動にできました。
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: EXPIRED
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: HIT
age: 1
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: EXPIRED
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: HIT
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: EXPIRED
HTTP/2 502
cache-control: max-age=315360000, public, stale-if-error=0
cf-cache-status: HIT
age: 1
まとめ
Cloudflare でステータスコードごとの Edge Cache TTL を確認することができました。
いくつか簡単なページを用意して意図した挙動を再現させることができれば、自信を持ってキャッシュ実装に進めると思います。
参考 : Apache オリジンでの Cache-Control ヘッダ追加
Header always append Cache-Control "max-age=315360000, public, stale-if-error=0"
# Header always append Cache-Control "max-age=31536000"
# Header always append Cache-Control "max-age=0"
参考 : Single File Purge
参考 : Purge Everything