在响应进入缓存前修正响应头:Cache Response Rules 的价值与实践

2026-07-24 41 预计阅读时间: 1 分钟
来源: blog.cloudflare.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

一个本应由边缘缓存直接返回的页面,有时会因为源站响应中的 Set-CookieCache-Control 被重新送回源站。麻烦在于,这些响应头可能来自旧框架、共享中间件或无法立即修改的托管服务。Cache Response Rules 提供了一个更合适的控制点:在响应进入缓存决策流程时修正这些头部,而不必先改造源站。

问题不一定出在缓存键

排查缓存未命中时,开发者通常先检查 URL、查询参数和缓存键。但缓存系统除了判断“两个请求是否相同”,还必须判断“这个响应能不能存”。

下面两类响应头经常影响后一个判断:

  • Set-Cookie:表示响应希望在客户端写入 Cookie,往往暗示内容可能与会话有关。
  • Cache-Controlprivateno-storeno-cache 等指令会限制共享缓存保存或复用响应。

例如,一个实际内容完全公开的静态页面,可能因为通用中间件附加了无关 Cookie:

HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: private, no-cache
Set-Cookie: tracking_id=abc123; Path=/

<html>...</html>

即使请求路径看起来适合缓存,响应头仍可能让边缘节点放弃缓存。结果是重复请求持续打到源站,增加延迟和源站负载。

Cache Response Rules 的关键意义不只是“能改响应头”,而是规则在缓存决策所需的时机生效。团队可以按主机名、路径或其他请求条件,定向移除意外的 Set-Cookie,或者把错误的缓存指令改成符合业务语义的值。

把规则限制在明确的公开内容上

响应头改写具有风险。Set-Cookieprivate 有时确实在保护用户数据,不能因为命中率不理想就全站删除。

适合采用这类规则的对象通常具有几个特征:

  • 响应内容对所有访问者一致。
  • 页面不依赖登录状态、地区、权限或实验分组。
  • 源站附加的 Cookie 与页面内容无关。
  • 团队能够用清晰的路径表达式限定规则范围。

可以这样实践。假设 /assets//public/ 下的内容已经确认是公开资源,可将规则表达为以下伪配置。字段名称需要按实际平台界面或 API 调整,这里只展示规则设计:

# 假设性示例:请映射到实际 Cache Response Rules 配置项
name: normalize-public-cache-headers
when:
  hostname: www.example.com
  path_prefix_any:
    - /assets/
    - /public/
actions:
  remove_response_headers:
    - Set-Cookie
  set_response_headers:
    Cache-Control: "public, max-age=300, s-maxage=3600"

这里刻意使用路径白名单,而不是对整个站点生效。max-age=300 控制浏览器缓存时间,s-maxage=3600 表达共享缓存可保存一小时;具体数值应依据内容更新频率确定。

不要把同样的规则套到 /account//checkout/ 或返回个性化信息的 API 上。否则共享缓存可能把一个用户的响应交给另一个用户。

用命令确认问题和改写结果

上线规则之前,先记录源站或边缘入口当前返回的关键头部。下面的脚本可以直接运行;将参数替换成要检查的 URL:

#!/usr/bin/env bash
set -euo pipefail

url="${1:-https://www.example.com/public/index.html}"

echo "Checking: $url"
curl --silent --show-error --output /dev/null --dump-header - "$url" \
  | tr -d '\r' \
  | awk 'BEGIN { IGNORECASE=1 }
    /^HTTP\// ||
    /^cache-control:/ ||
    /^set-cookie:/ ||
    /^age:/ ||
    /^etag:/ ||
    /^vary:/ ||
    /^cf-cache-status:/ ||
    /^x-cache:/ { print }'

保存为 check-cache.sh 后执行:

chmod +x check-cache.sh
./check-cache.sh https://www.example.com/public/index.html

应用规则后至少请求两次,因为第一次请求可能用于填充缓存:

for i in 1 2 3; do
  echo "--- request $i ---"
  ./check-cache.sh https://www.example.com/public/index.html
  sleep 2
done

验证时不要只寻找某个固定的命中标记。不同平台使用的诊断响应头不同,应重点确认:

  • 不需要的 Set-Cookie 是否只在目标路径上消失。
  • Cache-Control 是否变成预期值。
  • 重复请求是否出现缓存命中或 Age 增长迹象。
  • 登录页、账户页和个性化 API 是否仍保持不可共享缓存的行为。

还可以分别带上两组测试 Cookie 请求同一资源,比较响应体哈希,确认内容确实不随会话变化:

url="https://www.example.com/public/index.html"

curl -fsS -H 'Cookie: session=test-user-a' "$url" | sha256sum
curl -fsS -H 'Cookie: session=test-user-b' "$url" | sha256sum

哈希一致不能独立证明内容永远安全,但它能帮助发现明显的个性化差异。更稳妥的做法是结合应用代码、模板逻辑和权限模型进行审查。

上线时把安全边界放在命中率之前

Cache Response Rules 适合解决“源站响应语义错误,但源站暂时难改”的问题,也可以作为迁移期间的控制层。不过,它不应永久掩盖应用对缓存语义的误解。有条件时,仍应让源站为公开内容返回正确的 Cache-Control,并避免无意义地设置 Cookie。

上线前可以使用这份检查表:

  • 规则只匹配已经确认公开且非个性化的路径。
  • 已检查 Vary、认证头、Cookie 和地区化逻辑。
  • 缓存时间符合内容更新与回滚要求。
  • 已验证命中、未命中和过期后的行为。
  • 已准备快速禁用规则的操作路径。
  • 已监控源站请求量、缓存命中率和错误率。

这项能力真正解决的是控制位置问题:当难以在源站清理意外响应头时,在缓存做出决定之前进行精确修正。规则越窄、验证越充分,它带来的收益就越可靠。


相关推荐