对于可编辑的公开文档,如果希望读者获取当前内容,同时未更改的页面仍可重复使用,请选择重新验证。如果发布要求明确禁止 HTTP 缓存存储,请选择 no-store。

本指南面向使用 Mac 桌面设备管理公开文档的人。任务是选择响应策略,然后在 Terminal 中检查该策略,测试页面只包含中性文本,例如“形状指南,第一版”。你需要一个测试页面以及访问其托管配置的权限,或者需要托管服务提供商为你配置响应头。

哪种缓存策略适合这份文档?

从发布要求着手。页面每次重复使用前都需要检查吗?现有副本可以在短时间内继续使用吗?还是必须避免 HTTP 缓存存储该响应?根据 RFC 9111:HTTP 缓存,这些是不同的要求。

发布要求 候选响应头 对 HTTP 缓存的含义
每次重复使用前都检查 Cache-Control: no-cache 允许存储;重复使用前必须成功验证。
允许较短的有效期 Cache-Control: max-age=300, must-revalidate 响应新鲜时允许重复使用;响应过期后必须成功验证。
禁止存储响应 Cache-Control: no-store 缓存不得存储该响应,也不得将其用于其他请求。

五分钟的时间窗口只是示例,并非推荐的默认值。只有当文档能够接受这段重复使用时间时,才选择它。单独使用 must-revalidate 并不要求在响应仍新鲜时进行检查。这些区别遵循 RFC 9111 的响应指令。

以示例形状指南为例,假设要把“三个示例”改为“四个示例”,并且希望在下次检索时检查是否已更正。请从 no-cache 和可用的验证器开始。如果你的要求是 HTTP 缓存不得保留这份文档的响应,请选择 no-store。仅仅频繁编辑,并不能说明必须禁止存储。

更改设置前,先写明要求,例如:“重复使用前检查文档。”这样就有了明确的验收标准,也能避免让设置的名称替你决定策略。

重新验证如何生效?

验证器用于标识客户端已收到的版本。ETag 提供实体标签;Last-Modified 提供修改时间戳。RFC 9110 建议在成功检索文档时发送可用的验证器,优先同时发送强实体标签和修改日期。请参阅 HTTP 语义:验证器和 200 OK。

以下是用于说明的响应头字段,并非服务器配置代码。假设响应正文是示例形状指南:

Cache-Control: no-cache
ETag: "shape-guide-v1"

之后的请求中,客户端可以发送 If-None-Match: \"shape-guide-v1\"。如果该标签仍与所选表示相匹配,条件 GET 请求会收到 304 Not Modified,且不包含响应正文。如果标签已不匹配,正常处理流程可以返回已更改的文档。相关规则见 RFC 9110 的条件请求章节。

实现要求是验证器必须跟踪文档版本。不要把示例标签复制到永久配置中,然后在文档编辑后仍让它保持不变。请托管系统持续生成验证器,并评估传入的条件请求。

未更改的响应最多能减少多少传输量?

看一个明确标注为示例的计算:文档正文为 80,000 字节,客户端检索 100 次,期间没有任何编辑。传输一次完整响应后,再进行 99 次成功验证,传输的正文共 80,000 字节;如果每次都传输完整正文,则会传输 8,000,000 字节,相差 7,920,000 字节。

这个计算不包括响应头、压缩、连接开销以及任何应用程序处理量,只描述正文传输。Google 的 HTTP 缓存说明介绍了同样的交互:验证器匹配时,允许返回不带正文的 304,客户端则使用先前收到的内容。实际节省量取决于文档的更改频率和客户端的请求方式。

应在哪里配置策略?

在托管服务、服务器或内容分发层生成的 HTTP 响应中配置。上面的响应头示例描述了所需结果,并非适用于所有发布平台的通用命令。

如果你的编辑器只能修改文档文本,使用标记语言绕过限制并不能提供同等控制。WHATWG HTML 标准没有将 Cache-Control 定义为受支持的 http-equiv pragma,并说明这些 pragma 与 HTTP 响应头大体上相互独立。请参阅 HTML 标准:Pragma 指令。

受支持的做法是使用托管服务提供商文档中说明的响应头配置,或请服务提供商实施。Google 的爬虫概览也建议发布者联系托管或内容管理服务提供商来实现 HTTP 缓存。有效的请求应说明文档、所选策略和验证器行为,并询问如何验证实际发送的响应。

更改 JavaScript 请求选项的作用范围较窄。WHATWG 定义了一种 Fetch no-store 缓存模式,其行为如同不存在 HTTP 缓存;而 no-cache 会在存在适用的缓存响应时发起条件请求。这些模式只控制该请求;在脚本中设置模式,并不会配置文档服务器的响应策略。请参阅 Fetch 标准中的缓存模式。

如何在 Mac 上测试重新验证?

使用你可以编辑的公开测试文档。开始前,将其内容设为“形状指南,第一版”,并确保会发送所选响应头。此测试应与实际文档内容分开,这样你就能进行明显且可撤销的更改。

打开 Terminal,并在同一会话中运行以下命令。命令会提示你输入实际测试 URL 和页面返回的验证器;不会假设任何示例地址。如果第一个请求失败、发生重定向,或返回的不是预期文档响应,请停止操作。

printf '%s\n' 'Paste the full URL of your synthetic public test page:'
IFS= read -r page_url

curl --silent --show-error --connect-timeout 5 --max-time 20 \
  --dump-header - --output /dev/null --url "$page_url"

printf '%s\n' 'Paste its ETag value exactly, including quotes:'
IFS= read -r page_etag

check_page() {
  curl --silent --show-error --connect-timeout 5 --max-time 20 \
    --dump-header - --output /dev/null \
    --header "If-None-Match: $page_etag" --url "$page_url"
}

check_page

这些命令会发出 GET 请求、显示收到的响应头,并有意丢弃响应正文。超时设置会限制连接和传输时间;错误信息仍会显示。这些选项记载于 curl 手册。第一个请求应显示你选择的 Cache-Control 值和一个 ETag。如果没有标签,不要自行编造;先解决验证器支持问题。

复制完整标签值,包括两侧的引号和任何 W/ 前缀。如果表示内容未更改且标签匹配,条件请求应返回 304。304 不能包含内容,并且必须包含等效 200 响应中会附带的指定元数据,包括适用时的 ETag 和 Cache-Control。请参阅 RFC 9110:304 Not Modified。

保留旧验证器并测试编辑结果

将示例文档改为“形状指南,第二版:四个示例。”更新同步到测试页面后,在同一个 Terminal 会话中保留旧标签,并运行以下后续命令:

check_page

对于这份明确更改过的文档,应能通过正常的成功响应获取新正文,并收到更新后的验证器。接下来,使用新标签重复初始命令,再次检查未更改的版本。这会同时测试两种情况:识别更改,以及识别未更改。

观察结果 下一步诊断
初始请求返回重定向 使用文档的最终 URL,然后重新开始测试。
未更改的条件请求返回 200 检查标签是否复制正确,以及条件请求处理是否已启用。
内容有意更改后,使用旧标签仍返回 304 在依赖重新验证前,先调查更新传递和验证器生成情况。
实际发送的策略与配置不一致 检查负责生成最终响应的托管和分发设置。
请求超时或失败 先解决检索故障,再解读缓存行为。

这些只是诊断线索,并不能证明具体原因。此流程用于测试响应和条件请求交互,并不能确定所有浏览器都会如何处理。评估 no-store 时,请直接检查该响应指令。手动构造条件请求并不能测试浏览器是否存储了响应。

这对 Google 搜索意味着什么?

Google 当前的爬虫文档支持 ETag 搭配 If-None-Match,以及 Last-Modified 搭配 If-Modified-Since。文档建议 Google 的爬虫使用 ETag,并指出不同爬虫可能采用不同的缓存方式。请参阅 Google 爬虫和抓取工具概览。

该页面还指出其他 HTTP 缓存指令不受支持,同时另行建议将 max-age 与 Last-Modified 一起作为可能的重新抓取提示。鉴于文档说明了这一范围,不要假设面向浏览器的 no-store 或 no-cache 策略会决定 Googlebot 的抓取计划。请按文档说明的条件检索流程实现并测试验证器。

Google 解释说,304 会向其处理系统表明内容未更改;对于搜索而言,否则它不会影响索引编制。成功的 200 也不保证内容会被编入索引。相关说明见 HTTP 状态代码如何影响 Google 爬虫。

选择符合文档要求的策略,然后保留测试证据:初始响应、未更改时的条件响应,以及有意编辑后的响应。对于需要在重复使用前检查的公开文档,重新验证是一个实用的起点。如果禁止 HTTP 缓存存储本身就是要求,请选择 no-store。

来源