Internet 草案 No-Vary-Search 2026 年 6 月
Denicola 等人 2026 年 12 月 20 日到期 [页]
工作组:
超文本传输协议
Internet 草案:
draft-ietf-httpbis-no-vary-search-latest
发布日期:
预期状态:
标准轨道
到期:
作者:
D. Denicola
Google LLC
J. Roman
Google LLC
N. Jaju, 编。
Google LLC

No-Vary-Search HTTP 缓存扩展

摘要

本规范定义了对 HTTP 缓存的扩展,改变 URI 查询 参数影响缓存的方式。

关于本文档

本说明将在作为 RFC 发布前移除。

本草案的最新修订版可在 https://httpwg.org/http-extensions/draft-ietf-httpbis-no-vary-search.html 找到。 本文档的状态信息可在 https://datatracker.ietf.org/doc/draft-ietf-httpbis-no-vary-search/ 找到。

本文档的讨论在 HTTP 工作组邮件列表(mailto:ietf-http-wg@w3.org)上进行, 该邮件列表归档于 https://lists.w3.org/Archives/Public/ietf-http-wg/。 工作组信息可在 https://httpwg.org/ 找到。

本草案的源文件和问题跟踪器可在 https://github.com/httpwg/http-extensions/labels/no-vary-search 找到。

本备忘录的状态

本 Internet 草案完全按照 BCP 78 和 BCP 79 的规定提交。

Internet 草案是互联网工程任务组 (IETF)的工作文档。请注意,其他组织也可以将工作 文档作为 Internet 草案分发。当前 Internet 草案列表位于 https://datatracker.ietf.org/drafts/current/

Internet 草案是有效期最长为六个月的草案文档, 并且可在任何时候由其他文档更新、替换或废止。将 Internet 草案用作参考材料,或以“进行中的工作”之外的方式引用它们, 都是不适当的。

本 Internet 草案将于 2026 年 12 月 20 日到期。

目录

1. 引言

HTTP 缓存 [HTTP-CACHING] 基于复用在若干缓存键上匹配的资源,其中最重要的是所呈现的目标 URI([HTTP] 的第 7.1 节)。然而, 有时多个 URI 可以表示同一资源。这会导致缓存并不总是像本可做到的那样有用:如果缓存中包含某个 URI 下的响应, 但随后又在另一个 URI 下请求该响应,则缓存版本将被忽略。

`No-Vary-Search` 响应标头字段定义了一种缓存扩展,如 [HTTP-CACHING] 的第 4 节 所述, 它处理这一一般问题的一个特定子集,即仅在某些查询参数上不同的 URI 标识同一资源的情形。 它允许资源声明查询组件的某些或全部部分不会在语义上影响所提供的响应,因此可在缓存匹配目的中被忽略。 例如,如果查询参数的顺序不会影响所标识的资源,则可使用以下方式表示

No-Vary-Search: key-order

如果特定查询参数(例如用于分析的参数)不会在语义上影响所提供的资源, 则可使用以下方式表示

No-Vary-Search: params=("utm_source" "utm_medium" "utm_campaign")

如果资源反而想采用基于允许列表的方法,即只有 某些已知查询参数会在语义上影响所提供的响应,它们可以使用

No-Vary-Search: except=("productId")

请注意,通过发送唯一查询参数以避免取回 缓存响应的“缓存清除”可能会被 No-Vary-Search 标头字段变得无效。

第 3 节 使用 [STRUCTURED-FIELDS] 框架定义新的 响应标头字段 No-Vary-Search第 4 节第 5 节 说明字段值如何在规范中表示的数据模型,以及 将结构化字段解析器的原始输出解析为该数据模型的过程。第 6 节 给出用于比较 两个 URL 在该标头字段影响下是否等价的关键算法;值得注意的是,它依赖 [WHATWG-URL] 中指定的 application/x-www-form-urlencoded 格式 对查询组件给出的键和值分解。(因此,此 标头字段不适用于查询组件不遵循该格式的 URL。)最后,第 7 节 解释如何扩展 [HTTP-CACHING] 的第 4 节,以考虑这种新的等价性。

2. 约定和定义

本文档中的关键词“MUST”、“MUST NOT”、 “REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、 “MAY”和“OPTIONAL”应按 BCP 14 [RFC2119] [RFC8174] 中的描述解释,且仅当它们 如此处所示以全大写形式出现时才如此解释。

在本文档中,术语“URI”和“URL”会根据 上下文互换使用。“URI”用于 [URI][HTTP][HTTP-CACHING] 的上下文,而“URL”用于 [WHATWG-URL] 中指定的算法上下文。

本文档还采用 WHATWG 和 W3C 用法中常见的一些约定和记法, 尤其是在涉及算法时。见 [WHATWG-INFRA],特别是:

(其他使用的概念会通过内联引用指出。)

3. HTTP 标头字段定义

No-Vary-Search HTTP 标头字段是一个结构化字段 [STRUCTURED-FIELDS],其值 MUST 是一个字典([STRUCTURED-FIELDS] 的第 3.2 节)。

它具有以下创作一致性要求:

字典 MAY 包含键不是 key-orderparamsexcept 之一的条目, 但它们的含义不由本规范定义。本规范的实现将忽略此类条目(但未来 文档可能会为此类条目赋予含义)。

4. 数据模型

URL 变体配置由以下内容组成:

no-vary params

特殊值 wildcard 或字符串列表

vary params

特殊值 wildcard 或字符串列表

vary on key order

布尔值

默认 URL 变体 配置是这样一种 URL 变体配置:其 no-vary params 是空列表,vary params 是 wildcard,且 vary on key order 为 true。

获取 URL 变体配置 算法(第 5.2 节)确保 所有 URL 变体配置都遵循以下约束:

5. 解析

5.1. 解析 URL 变体 配置

给定 value,要解析 URL 变体 配置

  1. 如果 value 为 null,则返回 默认 URL 变体 配置。

  2. result 为新的 URL 变体配置。

  3. result 的 vary on key order 设为 true。

  4. 如果 value["key-order"] 存在:

    1. 如果 value["key-order"] 不是 布尔值,则返回 默认 URL 变体配置。

    2. result 的 vary on key order 设为 value["key-order"] 的布尔否定。

  5. 如果 value["params"] 和 value["except"] 均存在或均不存在,则返回 默认 URL 变体 配置。

  6. 如果 value["params"] 存在:

    1. 如果 value["params"] 不是 数组,则返回 默认 URL 变体配置。

    2. 如果 value["params"] 中的任一项 不是字符串,则返回 默认 URL 变体配置。

    3. result 的 no-vary params 设为 对 value["params"] 中每一项应用 解析键第 5.3 节)的结果。

    4. 如果 result 的 no-vary params 中的任一项是 错误,则返回 默认 URL 变体配置。

    5. result 的 vary params 设为 wildcard

  7. 否则,如果 value["except"] 存在:

    1. 如果 value["except"] 不是 数组,则返回 默认 URL 变体配置。

    2. 如果 value["except"] 中的任一项 不是字符串,则返回 默认 URL 变体配置。

    3. result 的 vary params 设为 对 value["except"] 中每一项应用 解析键第 5.3 节)的结果。

    4. 如果 result 的 vary params 中的任一项是 错误,则返回 默认 URL 变体配置。

    5. result 的 no-vary params 设为 wildcard

  8. 返回 result

5.2. 获取 URL 变体 配置

给定一个 response response,要获取 URL 变体 配置

  1. fieldValue 为给定 `No-Vary-Search` 和 "dictionary",从 response 的 header list 中 获取 结构化字段值 [FETCH] 的结果。

  2. 返回给定 fieldValue 后解析 URL 变体配置(第 5.1 节) 的结果。

5.2.1. 示例

以下从对最终 no-vary params 和 vary params 的影响角度, 说明各种输入如何被解析:

表 1
输入 结果
No-Vary-Search: params=("a") no-vary params: « "a" »
vary params: wildcard
No-Vary-Search: except=("x") no-vary params: wildcard
vary params: « "x" »
No-Vary-Search: params=() no-vary params:(空 列表)
vary params: wildcard
No-Vary-Search: except=() no-vary params: wildcard
vary params:(空列表)

以下输入均无效,并会导致返回 默认 URL 变体 配置:

  • No-Vary-Search: key-order="not a boolean"

  • No-Vary-Search: params="not an inner list"

  • No-Vary-Search: params=(not-a-string)

  • No-Vary-Search: params=?0

  • No-Vary-Search: params=?1

  • No-Vary-Search: params=?1, except=("x")

  • No-Vary-Search: params=("a"), except=("x")

  • No-Vary-Search: params=(), except=()

  • No-Vary-Search: except="not an inner list"

  • No-Vary-Search: except=(not-a-string)

  • No-Vary-Search: except=?1

以下输入是有效的,但有些不常规。它们与其更常规的形式 一并展示。

表 2
输入 常规形式
No-Vary-Search: key-order=?1 No-Vary-Search: key-order
No-Vary-Search: except=("x"), key-order No-Vary-Search: key-order, except=("x")
No-Vary-Search: params=() (省略该标头字段)
No-Vary-Search: key-order=?0 (省略该标头字段)

5.3. 解析键

给定 ASCII 字符串 keyString,要解析键

  1. keyByteskeyString同构编码 [WHATWG-INFRA]

  2. keyBytes 中的任何 0x2B (+) 替换为 0x20 (SP)。

  3. keyBytesDecodedkeyBytes百分号解码 [WHATWG-URL]

  4. keyStringDecodedkeyBytesDecoded不带 BOM 的 UTF-8 解码 [WHATWG-ENCODING]

  5. 返回 keyStringDecoded

5.3.1. 示例

解析键算法允许在 ASCII 结构化标头字段格式中 编码非 ASCII 键字符串,类似于 application/x-www-form-urlencoded 格式 [WHATWG-URL] 如何允许 在 URI(限制为 ASCII 字符)中编码键和值的整个条目列表。例如,

No-Vary-Search: params=("%C3%A9+%E6%B0%97")

将得到一个 URL 变体配置,其 vary params 为 « "é 気" »。如后面的示例所解释的,等价性测试期间的规范化过程 意味着这会将诸如下列 URI 视为等价:

  • https://example.com/?é 気=1

  • https://example.com/?é+気=2

  • https://example.com/?%C3%A9%20気=3

  • https://example.com/?%C3%A9+%E6%B0%97=4

等等,因为它们全都会被解析 [WHATWG-URL] 为具有相同的 键 "é 気"。

6. 比较

给定 URL 变体配置 variationConfig,两个 URL [WHATWG-URL] urlAurlB按变体配置 模等价的,如果以下 算法返回 true:

  1. 如果 urlAurlB 的 scheme、username、password、host、port 或 path 不同,则返回 false。

  2. 如果 variationConfig 等价于 默认 URL 变体配置, 则:

    1. 如果 urlA 的 query 等于 urlB 的 query,则 返回 true。

    2. 返回 false。

    在这种情况下,即使 URL 对在对其查询运行 application/x-www-form-urlencoded 解析器 [WHATWG-URL] 后可能看似相同, 例如 https://example.com/ahttps://example.com/a?,或 https://example.com/foo?a=b&&&chttps://example.com/foo?a=b&c=,也会被视为不等价。

  3. searchParamsAsearchParamsB 为空列表。

  4. 如果 urlA 的 query 不是 null,则将 searchParamsA 设为 给定 urlA 的 query 的 同构编码 [WHATWG-INFRA] 后运行 application/x-www-form-urlencoded 解析器 [WHATWG-URL] 的结果。

  5. 如果 urlB 的 query 不是 null,则将 searchParamsB 设为 给定 urlB 的 query 的 同构编码 [WHATWG-INFRA] 后运行 application/x-www-form-urlencoded 解析器 [WHATWG-URL] 的结果。

  6. 如果 variationConfig 的 no-vary params 是列表,则:

    1. searchParamsA 设为包含 searchParamsA 中那些项 pair 的列表,其中 variationConfig 的 no-vary params 不包含 pair[0]。

    2. searchParamsB 设为包含 searchParamsB 中那些项 pair 的列表,其中 variationConfig 的 no-vary params 不包含 pair[0]。

  7. 否则,如果 variationConfig 的 vary params 是列表,则:

    1. searchParamsA 设为包含 searchParamsA 中那些项 pair 的列表,其中 variationConfig 的 vary params 包含 pair[0]。

    2. searchParamsB 设为包含 searchParamsB 中那些项 pair 的列表,其中 variationConfig 的 vary params 包含 pair[0]。

  8. 如果 variationConfig 的 vary on key order 为 false,则:

    1. keyLessThan 为一个以两个 pair(keyAvalueA)和(keyBvalueB)为输入的算法,该算法 返回 keyA 是否按码元小于 [WHATWG-INFRA] keyB

    2. searchParamsA 设为用 keyLessThansearchParamsA 按升序 排序 [WHATWG-INFRA] 的结果。

    3. searchParamsB 设为用 keyLessThansearchParamsB 按升序 排序 [WHATWG-INFRA] 的结果。

  9. 如果 searchParamsA 的大小不等于 searchParamsB 的 大小,则返回 false。

  10. i 为 0。

  11. i < searchParamsA 的大小时:

    1. 如果 searchParamsA[i][0] 不等于 searchParamsB[i][0],则返回 false。

    2. 如果 searchParamsA[i][1] 不等于 searchParamsB[i][1],则返回 false。

    3. i 设为 i + 1。

  12. 返回 true。

6.1. 示例

由于 application/x-www-form-urlencoded 解析器规范化查询 字符串的方式,某些查询字符串虽然看起来并不明显等价, 但在解析后最终会被视为等价。

因此,例如,给定 No-Vary-Search 的任何非默认值, 如 No-Vary-Search: key-order,我们将得到以下等价关系:

表 3
第一个查询 第二个查询 说明
null ? null 查询与空字符串解析结果相同
?a=x ?%61=%78 解析会执行百分号解码
?a=é ?a=%C3%A9 解析会执行百分号解码
?a=%f6 ?a=%ef%bf%bd 两个值都会解析为 U+FFFD (�)
?a=x&&&& ?a=x 解析会按 & 分割并 丢弃空字符串
?a= ?a 二者都解析为对 a 具有空字符串值
?a=%20 ?a= & %20 会解析为 U+0020 SPACE
?a=+ ?a= & + 会解析为 U+0020 SPACE

7. 缓存

如果缓存 [HTTP-CACHING] 实现本规范,则 [HTTP-CACHING] 的第 4 节 中的呈现目标 URI 要求:

所呈现的目标 URI([HTTP] 的第 7.1 节)与所存储响应的目标 URI 匹配,且

替换为:

所呈现的目标 URI([HTTP] 的第 7.1 节)与所存储响应的目标 URI 匹配或 按 URL 变体配置模等价,且

缓存实现 MAY 不复用其目标 URI 仅按 URL 变体配置模匹配的已存储响应,如果该缓存最近已 存储了一个响应,该响应:

为了帮助提高缓存实现效率,服务器 SHOULD NOT 对某个给定 pathname 的请求随时间发送不同的非空 No-Vary-Search 字段值, 除非需要更新它们处理 query 组件的方式。这样做 会导致使用上述策略的缓存实现错过一些本可被复用的已存储响应。

8. 安全考虑事项

需要注意的主要风险是 URL 不匹配的影响。具体而言,这可能 导致用户看到的响应最初取自一个不同于其悬停链接时所显示 URL 或 URL 栏中所显示 URL 的 URL。

然而,由于影响仅限于查询参数,这不会跨越 相关的安全边界,即 origin [HTML]。(或者从 Web 浏览器 安全 UI 的角度,也许只是 host[WHATWG-URL]) 确实,我们已经给予 origin 对其如何呈现 (URL, response body) 对的完全控制, 包括在客户端通过 history.replaceState() 或 service workers 等技术来控制。

9. 隐私考虑事项

本提案邻近高度涉及隐私的导航跟踪领域, 该领域通常使用查询参数传递用户标识符。然而,我们认为本提案 本身没有隐私影响。它不会干扰现有的 导航跟踪缓解措施,也不会干扰任何已知正在考虑的未来措施。事实上,如果 页面在其 URI 中编码用户标识符,本提案提供的唯一能力是 通过阻止服务器处理此类用户 ID(因为服务器会被绕过而使用缓存) 来减少此类用户跟踪。[NAV-TRACKING-MITIGATIONS]

10. IANA 考虑事项

10.1. HTTP 字段名称

请求 IANA 将以下内容录入超文本传输协议 (HTTP) 字段名称注册表(https://www.iana.org/assignments/http-fields/http-fields.xhtml):

字段名称:

No-Vary-Search

状态:

永久

结构化类型:

字典

参考:

本文档

备注:

(无)

11. 参考文献

11.1. 规范性参考文献

[FETCH]
van Kesteren, A., "Fetch 现行标准", n.d., <https://fetch.spec.whatwg.org/>. WHATWG
[HTTP]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP 语义", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/rfc/rfc9110>.
[HTTP-CACHING]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP 缓存", STD 98, RFC 9111, DOI 10.17487/RFC9111, , <https://www.rfc-editor.org/rfc/rfc9111>.
[RFC2119]
Bradner, S., "用于 RFC 中表示 要求级别的关键词", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174]
Leiba, B., "RFC 2119 关键词中大写与 小写的歧义", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[STRUCTURED-FIELDS]
Nottingham, M. and P. Kamp, "HTTP 的结构化字段值", RFC 9651, DOI 10.17487/RFC9651, , <https://www.rfc-editor.org/rfc/rfc9651>.
[URI]
Berners-Lee, T., Fielding, R., and L. Masinter, "统一资源 标识符(URI):通用语法", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.
[WHATWG-ENCODING]
van Kesteren, A., "Encoding 现行标准", n.d., <https://encoding.spec.whatwg.org/>. WHATWG
[WHATWG-INFRA]
van Kesteren, A. and D. Denicola, "Infra 现行标准", n.d., <https://infra.spec.whatwg.org/>. WHATWG
[WHATWG-URL]
van Kesteren, A., "URL 现行标准", n.d., <https://url.spec.whatwg.org/>. WHATWG

11.2. 资料性参考文献

[HTML]
van Kesteren, A., "HTML 现行标准", n.d., <https://html.spec.whatwg.org/>. WHATWG
Snyder, P. and J. Yasskin, "导航跟踪缓解措施", n.d., <https://privacycg.github.io/nav-tracking-mitigations/>. W3C Privacy CG

致谢

本文档受益于以下人员有价值的审阅和建议:

索引

D E O P

作者地址

Domenic Denicola
Google LLC
Jeremy Roman
Google LLC
Nidhi Jaju(编辑
Google LLC