Purge by single-file を API から利用する(ダッシュボードでできない部分の対応)
はじめに
Cloudflare CDN キャッシュの Purge by single-file(URL)について、API で操作する場合の利用例をメモしておきます。
シングルファイル(URL)の Purge はダッシュボードから実施できるのですが(全プラン)、
下記のような場合は Purge できません。
-
標準のキャッシュキーの対象になるヘッダー付きのリクエスト
-
カスタムキャシュキー利用時
例外 Device type と Country についてはダッシュボードの Advanced からも利用可能)
これらのリクエストをシングルファイル Purge する方法は API コールになります。
キャッシュキーの変更は Cache rules から行います。
そのため、以下でその設定に応じた API での Purge 方法を見ていきます。
API 利用例
URL のみの指定で Purge するケース
デフォルトのキャッシュキー
ダッシュボード同等のシングルファイルパージは下記のようなボディを指定します。
ダッシュボードの場合、この url の値だけを入力していることになります。
まずはクエリーストリングがない URL です。
{
"files": [
{"url": "https://www.example.com/foo"}
]
}
log
# Cloudflare でキャッシュ中
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: HIT
# API から Purge 実行
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'"}
]
}'
# キャッシュ MISS となり Purge 成功
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: MISS
リクエストにクエリーストリングがついている場合、デフォルトではクエリーストリングをキャッシュキーに含みます。
Purge も対象のクエリーストリング込みで url に指定して実行します。
{
"files": [
{"url": "https://www.example.com/foo?id=1"}
]
}
log
# クエリーストリング 1 をキャッシュ
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 2 をキャッシュ
http -h "$TARGET?id=2" | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h "$TARGET?id=2" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET?id=1"'"}
]
}'
# クエリーストリング 2 は Hit
http -h "$TARGET?id=2" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 1 は Miss(Purge 成功)
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
複数のクエリーストリングがある場合、a=0&b=1
と b=1&a=0
のような順番違いは違うキャッシュキーで扱われます。
下記のように指定すると、前者だけ Purge されます。
後者を Purge するには b=1&a=0
を指定します。
{
"files": [
{"url": "https://www.example.com/foo?a=0&b=1"}
]
}
log
# クエリーストリング 1 をキャッシュ
http -h "$TARGET?a=0&b=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h "$TARGET?a=0&b=1" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 2 をキャッシュ
http -h "$TARGET?b=1&a=0" | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h "$TARGET?b=1&a=0" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET?a=0&b=1"'"}
]
}'
# クエリーストリング 2 は Hit
http -h "$TARGET?b=1&a=0" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 1 は Miss(Purge 成功)
http -h "$TARGET?a=0&b=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
Cache rules でキャッシュキーを変更
デフォルトのキャッシュキーを変更していきます。
クエリーストリングをソート 📖
クエリーストリングがソートされ a=0&b=1
と b=1&a=0
のような順番違いは同じキャッシュキーになります。
a=0&b=1
・b=1&a=0
どちらで指定しても同じように Purge されます。
{
"files": [
{"url": "https://www.example.com/foo?a=0&b=1"}
]
}
log
# クエリーストリング 1 をキャッシュ
http -h "$TARGET?a=0&b=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
# クエリーストリング 2 も同じキャッシュから返信
http -h "$TARGET?b=1&a=0" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET?a=0&b=1"'"}
]
}'
# クエリーストリング 2 が MISS(Purge 成功)
http -h "$TARGET?b=1&a=0" | grep -i cf-cache-status
CF-Cache-Status: MISS
クエリーストリングを無視 📖
クエリーストリングを無視する場合、Purge もクエリーストリングを指定せず実行します。
任意のクエリーストリングをつけたとしても Purge されます。
{
"files": [
{"url": "https://www.example.com/foo"}
]
}
log
# クエリーストリング 1 をキャッシュ
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クエリーストリング 2 も同じキャッシュから返信
http -h "$TARGET?id=2" | grep -i cf-cache-status
CF-Cache-Status: HIT
# URL を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'"}
]
}'
# クエリーストリング 1 が MISS(Purge 成功)
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
# 適当なクエリーストリングをつけても無視され Purge される
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET?hoge=2345"'"}
]
}'
http -h "$TARGET?id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
URL + Headers の指定で Purge するケース
標準でキャッシュキーの対象になるヘッダーをもつリクエスト
デフォルトでキャッシュキーに入るヘッダーをもったキャッシュを Purge します。
リクエストヘッダー |
---|
Origin X-Forwarded-Host X-Host X-Forwarded-Scheme X-Original-URL X-Rewrite-URL Forwarded |
url に加え、 headers に当該のヘッダーと値を追加して Purge を発行します。
例えば Origin ヘッダー付きのリクエストのキャッシュを Purge する場合は下記のようになります。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"origin":"https://example.net"}}
]
}
log
# Origin ヘッダー 1 をキャッシュ
http -h $TARGET origin:https://example.com | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET origin:https://example.com | grep -i cf-cache-status
CF-Cache-Status: HIT
# Origin ヘッダー 2 をキャッシュ
http -h $TARGET origin:https://example.net | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET origin:https://example.net | grep -i cf-cache-status
CF-Cache-Status: HIT
# Origin ヘッダー 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"origin":"https://example.com"}}
]
}'
# Origin ヘッダー 2 は Hit
http -h $TARGET origin:https://example.net | grep -i cf-cache-status
CF-Cache-Status: HIT
# Origin ヘッダー 1 は Miss(Purge 成功)
http -h $TARGET origin:https://example.com | grep -i cf-cache-status
CF-Cache-Status: MISS
Cache rules でキャッシュキーを変更
デフォルトのキャッシュキーを変更していきます。
指定のリクエストヘッダーと値 📖
指定のリクエストヘッダーとその値をキャッシュキーに追加します。
Purge も headers に当該ヘッダーと値を格納して実行します。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"z-id":"1"}}
]
}
log
# ヘッダー 1 をキャッシュ
http -h $TARGET z-id:1 | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET z-id:1 | grep -i cf-cache-status
CF-Cache-Status: HIT
# ヘッダー 2 をキャッシュ
http -h $TARGET z-id:2 | grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET z-id:2 | grep -i cf-cache-status
CF-Cache-Status: HIT
# ヘッダー 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"z-id":"1"}}
]
}'
# ヘッダー 2 は Hit
http -h $TARGET z-id:2 | grep -i cf-cache-status
CF-Cache-Status: HIT
# ヘッダー 1 は MISS (Purge 成功)
http -h $TARGET z-id:1 | grep -i cf-cache-status
CF-Cache-Status: MISS
指定のリクエストヘッダーの存在 📖
指定のリクエストヘッダーが存在することをキャッシュキーに使用します(boolean)。
当該ヘッダーと値(何でもよい)を設定し Purge を実行します。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"z-id":"hoge"}}
]
}
log
# ヘッダー 1 を キャッシュ
http -h "$TARGET" z-id:1 | grep -i cf-cache-status
CF-Cache-Status: MISS
# ヘッダー 2 も同じキャッシュ
http -h "$TARGET" z-id:2 | grep -i cf-cache-status
CF-Cache-Status: HIT
# 指定のヘッダー(値は任意)を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"z-id":"hoge"}}
]
}'
# ヘッダー 2 が MISS (Purge 成功)
http -h "$TARGET" z-id:2 | grep -i cf-cache-status
CF-Cache-Status: MISS
指定の Cookie と値 📖
指定の Cookie とその値をキャッシュキーに加えます。
Purge も headers で当該の Cookie と値を格納し実行します。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"cookie":"z-id=1"}}
]
}
log
# クッキー 1 を キャッシュ
http -h "$TARGET" cookie:"z-id=1" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クッキー 2 を キャッシュ
http -h "$TARGET" cookie:"z-id=2" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クッキー 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"cookie":"z-id=1"}}
]
}'
# クッキー 2 は HIT
http -h "$TARGET" cookie:"z-id=2" | grep -i cf-cache-status
CF-Cache-Status: HIT
# クッキー 1 は MISS(Purge 成功)
http -h "$TARGET" cookie:"z-id=1" | grep -i cf-cache-status
CF-Cache-Status: MISS
指定の Cookie の存在 📖
指定の Cookie が存在することをキャッシュキーに使用します(boolean)。
当該 Cookie と値(何でもよい)を設定し Purge を実行します。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"cookie":"z-id=hoge"}}
]
}
log
# クッキー 1 をキャッシュ
http -h "$TARGET" cookie:z-id=1 | grep -i cf-cache-status
CF-Cache-Status: HIT
# 指定のクッキー(値は任意)を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"cookie":"z-id=hoge"}}
]
}'
# クッキー 2 が MISS(Purge 成功)
http -h "$TARGET" cookie:z-id=1 | grep -i cf-cache-status
CF-Cache-Status: MISS
Device type 📖
または
どっちかだけ設定する
両方設定しようとするとエラーになります。
API での設定箇所
Cache rules API での出力です。
# トグル指定時
{
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"cache_key": {
"cache_by_device_type": true
}
},
# チェックボックス指定時
{
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"cache_key": {
"custom_key": {
"user": {
"device_type": true
}
}
}
},
オリジン転送時に追加されるヘッダー
どちらの方式でもオリジンサーバーへのリクエストには下記のヘッダーが追加されます。
# desktop, mobile, tablet のどれか
Cf-Device-Type: desktop
Cloudflare が判断するデバイスタイプをキャッシュキーに追加します。
User agent により 3 種に分類し cf-device-type ヘッダーに追加されます。
Purge も headers に cf-device-type とそのタイプを指定します。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"cf-device-type":"mobile"}}
]
}
log
# ユーザーエージェント 1 を キャッシュ
http -h $TARGET user-agent:$ANDROID | grep -i cf-cache-status
CF-Cache-Status: HIT
# ユーザーエージェント 2 を キャッシュ
http -h $TARGET user-agent:$WINDOWS | grep -i cf-cache-status
CF-Cache-Status: HIT
# デバイスタイプ mobile を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"cf-device-type":"mobile"}}
]
}'
# ユーザーエージェント 2 は HIT
http -h $TARGET user-agent:$WINDOWS | grep -i cf-cache-status
CF-Cache-Status: HIT
# ユーザーエージェント 1 は MISS(Purge 成功)
http -h $TARGET user-agent:$ANDROID | grep -i cf-cache-status
CF-Cache-Status: MISS
Country 📖
Cloudflare が見たクライアントの国コード(2 文字)をキャッシュキーに追加します cf-ipcountry 。
Purge は headers で cf-ipcountry を指定しますが、国コードは大文字で指定する必要がありました。
cf-ipcountry ヘッダーについて
Cf-Ipcountry は標準でオリジンに通知されるヘッダーの一つです。
Cf-Ipcountry: JP
HTTP ログで確認することも可能です。
Instant logs の例
余談ですが、これを使うと他の情報も色々取れます。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"cf-ipcountry":"JP"}}
]
}
log
# 日本からのリクエストをキャッシュ
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: HIT
# オーストラリアからのリクエストを キャッシュ
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: HIT
# 国コード JP を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"cf-ipcountry":"JP"}}
]
}'
# オーストラリアからのリクエストは HIT
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: HIT
# 日本からのリクエストは MISS(Purge 成功)
http -h $TARGET | grep -i cf-cache-status
CF-Cache-Status: MISS
Language 📖
リクエストヘッダー accept-language の値をキャッシュキーに利用します。
Purge も headers に accept-language とその値を格納します。
値はリクエストの大文字・小文字との完全マッチになります。
下記の場合リクエストが ja は効くが、Ja のときはマッチしません。
{
"files": [
{"url": "https://www.example.com/foo", "headers": {"accept-language":"ja"}}
]
}
log
# accept-language:ja をキャッシュ
http -h $TARGET accept-language:ja | grep -i cf-cache-status
CF-Cache-Status: HIT
# accept-language:de をキャッシュ
http -h $TARGET accept-language:de | grep -i cf-cache-status
CF-Cache-Status: HIT
# accept-language:ja を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"accept-language":"ja"}}
]
}'
# accept-language:de は HIT
http -h $TARGET accept-language:de | grep -i cf-cache-status
CF-Cache-Status: HIT
# accept-language:ja は MISS(Purge 成功)
http -h $TARGET accept-language:ja | grep -i cf-cache-status
CF-Cache-Status: MISS
# 指定する値の大文字・小文字はリクエストヘッダーと合わせる
# リクエストヘッダーとあっていないと効かない
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'", "headers": {"accept-language":"DE"}}
]
}'
http -h $TARGET accept-language:de | grep -i cf-cache-status
CF-Cache-Status: HIT
# 大文字・小文字でキャッシュキーが変わる
http -h $TARGET accept-language:ja-jp | grep -i cf-cache-status
CF-Cache-Status: HIT
http -h $TARGET accept-language:ja-Jp | grep -i cf-cache-status
CF-Cache-Status: MISS
その他
Cache rules でキャッシュキーを変更
Host ヘッダー 📖
オリジン接続時にホストヘッダーを書き換えます。
この書き換えたホストヘッダーをキャッシュキーに利用します。
シングルファイルでの Purge 方法は探し中です。
代案としてシングルファイルでなくホスト名指定で Purge 可能なことは確認しました。
{
"hosts": [
"o1.oymk.work"
]
}
ホストヘッダーの書き換え方
ホストヘッダーは Origin rules で書き換えることができます。
下記は cookie の値によってホストヘッダーを書き換えています。
log
# Origin 1 をキャッシュ
http -h $TARGET cookie:"o=1"| grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET cookie:"o=1"| grep -i cf-cache-status
CF-Cache-Status: HIT
# Origin 2 をキャッシュ
http -h $TARGET cookie:"o=2"| grep -i cf-cache-status
CF-Cache-Status: MISS
http -h $TARGET cookie:"o=2"| grep -i cf-cache-status
CF-Cache-Status: HIT
# オリジン側では異なるホスト名で受信している
o1.oymk.work - "GET /custom/ts.bin HTTP/2.0" 200 3 "-" "HTTPie/3.2.4"
o2.oymk.work - "GET /custom/ts.bin HTTP/2.0" 200 3 "-" "HTTPie/3.2.4"
# オリジン 1 を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"hosts": [
"o1.oymk.work"
]
}'
# オリジン 2 は HIT
http -h $TARGET cookie:"o=2"| grep -i cf-cache-status
CF-Cache-Status: HIT
# オリジン 1 は MISS(Purge 成功)
http -h $TARGET cookie:"o=1"| grep -i cf-cache-status
CF-Cache-Status: MISS
Origin ヘッダー 📖
オリジンヘッダーをキャッシュキーから抜きます。
Purge もオリジンヘッダーを指定しないで実行します。
{
"files": [
{"url": "https://www.example.com/foo"}
]
}
log
# オリジン 1 でキャッシュ
http -h $TARGET origin:https://example.com | grep -i cf-cache-status
CF-Cache-Status: MISS
# オリジン 2 も同じキャッシュ
http -h $TARGET origin:https://example.net | grep -i cf-cache-status
CF-Cache-Status: HIT
# オリジン指定せず Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'"}
]
}'
# オリジン 2 が MISS(Purge 成功)
http -h $TARGET origin:https://example.net | grep -i cf-cache-status
CF-Cache-Status: MISS
Cache deception armor 📖
Cache deception armor が有効なときでも Purge はデフォルトの URL に対して発行します。
Cache deception armor について
こちらの blog で
Origin Cache Control も有効に
Cache detection armor を有効にするには Origin Cache Control を有効にします。
{
"files": [
{"url": "https://www.example.com/foo"}
]
}
log
# リクエストのファイル拡張子とレスポンスのコンテントタイプが一致しない
GET /deception/foo.jpg HTTP/1.1
# jpg に対してオリジンから application/json の応答のため
# Cache deception armor で BYPASS
# ‐ Cache deseption armor 無効だとキャッシュされる
HTTP/1.1 200 OK
CF-Cache-Status: BYPASS
Content-Type: application/json; charset=utf-8
# リクエストのファイル拡張子とレスポンスのコンテントタイプが一致する
GET /deception/foo.png HTTP/1.1
# png に対してオリジンから image/png の応答のため
# Cache し HIT
HTTP/1.1 200 OK
CF-Cache-Status: HIT
Content-Type: image/png
# URL で png を Purge
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $API_TOKEN" \
-d '{
"files": [
{"url": "'"$TARGET"'"}
]
}'
# MISS に変わる(Purge 成功)
HTTP/1.1 200 OK
CF-Cache-Status: MISS
さいごに
API でのシングルファイル(URL)の Purge ができることを確認しました。
URL(files)を複数指定したり、キャッシュキーに複数項目を追加するような場合は示しませんでしが、API の例にあるような形になります。
なお Cloudflare Workers の fetch API・cache API での Purge についてはこちらに説明があります。
別途試せたらと思います。
Discussion