| 互联网工程任务组 (IETF) | J. Reschke |
| 征求意见稿: 10008 | greenbytes |
| 类别: 标准轨道 | J. Snell |
| ISSN: 2070-1721 | Cloudflare |
| M. Bishop | |
| Akamai | |
| 2026 年 6 月 |
HTTP QUERY 方法
摘要
本规范定义了 HTTP 的 QUERY 方法。QUERY 要求请求 目标以安全且幂等的方式处理所附内容,然后以 该处理的结果作出响应。这与 POST 请求类似,但 QUERY 请求可以 自动重复或重新开始,无需担心部分状态变更。
本备忘录的状态
这是一份互联网标准轨道文档。
本文档是互联网工程任务组 (IETF) 的成果。它代表了 IETF 社区的共识。它已经过公开审查,并已获 互联网工程指导组 (IESG) 批准发布。有关 互联网标准的更多信息,请参阅 RFC 7841 第 2 节。
有关本文档当前状态、任何勘误以及如何提供 反馈的信息,可通过以下地址获取:https://www.rfc-editor.org/info/rfc10008。
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.
1. 引言
一种常见的查询模式如下:
GET /feed?q=foo&limit=10&sort=-published HTTP/1.1 Host: example.org
但是,当传递的数据过多,以至于无法编码到请求的 URI 中时,这种 模式就会出现问题:
作为使用 GET 的替代方案,许多实现使用 HTTP POST 方法来 执行查询,如下例所示。在这种情况下,查询 操作的输入作为请求内容传递,而不是使用请求 URI 的查询 组件。
使用 HTTP POST 请求查询的典型方式如下:
POST /feed HTTP/1.1 Host: example.org Content-Type: application/x-www-form-urlencoded q=foo&limit=10&sort=-published
然而,在这种变体中,如果不了解 请求所发往的资源和服务器的具体情况,就无法轻易看出正在执行的是安全、幂等的查询 操作。
QUERY 方法提供了一种填补 GET 与 POST 用法之间空白的解决方案, 上述示例可表示为:
QUERY /feed HTTP/1.1 Host: example.org Content-Type: application/x-www-form-urlencoded q=foo&limit=10&sort=-published
与 POST 一样,查询操作的输入作为请求内容传递,而 不是作为请求 URI 的一部分。不过,与 POST 不同,该方法明确具有安全性和 幂等性,因此可以使用缓存和自动重试等功能。
基于任何重要资源都应由 URI 标识这一设计原则, 本规范描述了服务器如何为查询本身或 特定查询结果分配 URI,以便稍后在 GET 请求中使用。
总结如下:
| GET | QUERY | POST | |
|---|---|---|---|
| 安全 | 是 | 是 | 可能不是 |
| 幂等 | 是 | 是 | 可能不是 |
| 查询本身的 URI | 是(按定义) | 可选(Location 响应字段) | 否 |
| 查询结果的 URI | 可选(Content-Location 响应 字段) | 可选(Content-Location 响应 字段) | 可选(Content-Location 响应 字段) |
| 可缓存 | 是 | 是 | 是,但仅用于后续 GET 或 HEAD 请求 |
| 内容(正文) | “未定义语义” | 预期存在(语义由目标 资源决定) | 预期存在(语义由目标 资源决定) |
1.1. 术语
1.2. 符号约定
2. QUERY 方法
QUERY 方法用于发起服务器端查询。GET 方法 请求目标 URI 所标识资源的表示(定义见 第 7.1 节,位于 [HTTP]),而 QUERY 方法 用于要求目标资源在该目标 资源的范围内执行查询操作。
请求内容及其媒体类型定义了查询。源服务器根据 目标资源确定操作的范围。
与所有 HTTP 方法一样,目标 URI 的查询部分参与标识 被查询的资源。它是否以及如何直接影响查询结果,取决于 具体资源,不在本规范的范围内。
QUERY 请求对于目标资源是安全的 ([HTTP],第 9.2.1 节); 也就是说,客户端既不请求也不预期目标 资源的状态发生任何变化。这并不妨碍服务器创建额外的 HTTP 资源, 通过这些资源可检索更多信息(参见第 2.3 节和第 2.4 节)。
具体而言,200(成功)响应表示查询已被成功处理, 且该处理的结果作为响应内容包含在内。
2.1. 媒体类型与内容协商
QUERY 请求的语义同时取决于请求内容和相关的 元数据,例如媒体类型 ([HTTP],第 8.3.1 节)。 一般而言,对于内容与元数据不一致的请求所存在的任何问题,都必须使用 4xx(客户端错误)响应予以拒绝 ([HTTP],第 15.5 节)。
以下列表描述了各种失败情况,并建议了具体的状态码:
- 如果请求缺少媒体类型信息,则按定义它就是不正确的,需要 使用 4xx 状态码使其失败,例如 400(客户端错误)。
- 如果指定了媒体类型,但资源不支持该类型,则适合使用 415 (不支持的媒体类型)。这明确包括以下情况: 原则上已知该媒体类型,但它缺少针对 目标资源的 QUERY 的特定语义。在这两种情况下,Accept-Query 响应字段 (第 3 节) 可用于告知客户端所支持的媒体类型。
- 如果指定了媒体类型,但它与实际请求内容不一致,则 可以返回 400(错误请求)。也就是说,不允许服务器根据请求内容推断媒体 类型,然后覆盖缺失或“错误”的值 (即“内容嗅探”)。
- 如果指定的媒体类型已被理解,且内容确实与 该类型一致,但由于查询的实际内容而无法处理 查询,则可以使用状态码 422(无法处理的内容)。例如, 语法正确的 SQL 查询标识了一个不存在的表。
- 如果客户端使用 Accept 字段 ([HTTP],第 12.5.1 节) 请求了资源不支持的特定响应媒体类型,则适合使用 406(不可 接受)状态码。
2.2. 等价资源
对于任意给定的 QUERY 请求,其等价资源是一个响应 GET 请求、代表该 QUERY 请求及其目标,并同时考虑消息 内容和元数据的资源 (第 6 节,见 [HTTP])。具体而言,这 包括表示元数据 (第 8 节,见 [HTTP]),例如 内容的媒体类型。
换言之,等价资源是通过纳入请求内容, 从实现 QUERY 的资源派生而来的。
2.3. Content-Location 响应字段
成功响应(2xx,第 15.3 节,见 [HTTP])可以包含一个 Content-Location 首部字段,其中包含与 操作结果对应的资源标识符;详情参见 第 8.7 节,位于 [HTTP]。这 表示服务器声明:客户端可以向 指定 URI 发送 GET 请求,以检索刚刚执行的查询操作的结果。所 指示的资源可能是临时的。
参见附录 A.4.1 中的示例。
2.4. Location 响应字段
服务器可以为 QUERY 请求的等价资源 (第 2.2 节) 分配 URI。如果服务器这样 做,则可以将该资源的 URI 包含在 2xx 响应的 Location 首部字段中(参见 第 10.2.2 节, 位于 [HTTP])。这表示 服务器声明:客户端可以向指定 URI 发送 GET 请求,以重复刚刚执行的查询 操作,而无需重新发送查询内容。此资源的 URI 可能 是临时的;如果后续请求失败,客户端可以使用原始 QUERY 请求目标和之前提交的内容重试。
参见附录 A.4.2 中的示例。
2.5. 重定向
状态码为 301(永久移动,[HTTP],第 15.4.2 节)或 308(永久重定向,[HTTP],第 15.4.9 节)的响应,表示目标资源已永久移动到 Location 响应字段所引用的其他 URI ([HTTP],第 10.2.2 节)。同样,状态码为 302(找到,[HTTP],第 15.4.3 节)或 307(临时重定向,[HTTP],第 15.4.8 节)的响应,表示目标资源已临时移动。在这四种 情况下,服务器都在建议用户代理可以通过 向 Location 所引用的新目标 URI 发送类似的 QUERY 请求, 来完成其原始 QUERY 请求。
请注意,在收到 301 或 302 响应后将 POST 重定向为 GET 请求的例外情况,不适用于 QUERY 请求。
状态码为 303(参见其他,第 15.4.4 节, 见 [HTTP])的 QUERY 响应表示, 原始查询可以通过对 Location 响应字段所引用的 URI 发出普通检索请求来完成 ([HTTP],第 10.2.2 节)。对于 HTTP,这意味着向新目标 URI 发送 GET 请求,如 以下示例所示:附录 A.4.3。
2.6. 条件请求
参见附录 A.5 中的 示例。
2.7. 缓存
QUERY 方法的响应是可缓存的;缓存可以使用它来 满足后续的 QUERY 请求,依据 第 4 节,位于 [HTTP-CACHING]。
QUERY 请求的缓存键 (第 2 节,见 [HTTP-CACHING]) 必须纳入请求内容 (第 6 节,见 [HTTP-CACHING]) 及相关 元数据 (第 8 节, 见 [HTTP])。
为提高缓存效率,缓存可以先移除请求内容和相关元数据中 在语义上无关紧要的差异。例如, 通过:
请注意,任何此类转换都仅用于生成 缓存键;它不会更改请求本身。
客户端可以使用 "no-transform" 缓存指令 (第 5.2.1.6 节,见 [HTTP-CACHING]),表明它们希望 不发生此类转换(但请注意,此指令仅具有建议性质)。
2.8. 范围 请求
查询格式通常会定义自身限制结果集或对结果集分页的方式,例如 SQL 中的 "FETCH FIRST ... ROWS ONLY"。预计将使用这些内置功能 来替代 HTTP 范围请求。
3. Accept-Query 首部字段
资源可以使用 "Accept-Query" 响应首部字段,直接表明支持 QUERY 方法,同时标识可以 使用的具体查询格式媒体类型。
Accept-Query 包含一个媒体范围列表 (第 12.5.1 节,见 [HTTP]),使用“结构化字段” 语法 [STRUCTURED-FIELDS]。媒体 范围由元素为 Token 或 String 的 List 结构化首部字段表示, 包含不带参数的媒体范围值。
媒体类型参数(如果有)映射为类型为 String 或 Token 的结构化字段参数。选择 Token 还是 String 在语义上无关紧要。也就是说, 接收方可以将 Token 转换为 String,但不 得根据接收到的类型对它们进行不同处理。
媒体类型并不与 Token 完全对应;例如,媒体类型允许以数字开头。在 这类情况下,需要使用 String 格式。
唯一支持的通配符用法是匹配任意类型的 "*/*",或 匹配指定类型的任意子类型的 "xxxx/*"。
字段值中所列类型的顺序无关紧要。
Accept-Query 字段的值适用于服务器上具有相同 路径的每一个 URI;换言之,查询组件被忽略。如果对同一资源的请求 返回不同的 Accept-Query 值,则使用最近收到的新鲜值(依据 第 4.2 节,位于 [HTTP-CACHING])。
例如:
Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
尽管此字段的语法看起来与其他字段类似,例如 "Accept" (第 12.5.1 节,见 [HTTP]),但它是结构化字段, 因此必须按照以下位置的规定处理:第 4 节,位于 [STRUCTURED-FIELDS]。
4. 安全注意事项
QUERY 方法与所有 HTTP 方法一样,受相同的一般安全注意事项约束, 如 [HTTP] 所述。
它可替代在 URI 中传递请求信息的方式(例如,在 查询组件中)。在某些情况下,这种方式更可取,因为与请求内容相比,URI 更可能被中间设备记录到日志中或 以其他方式处理。在其他情况下,如果 查询包含敏感信息,URI 可能被记录到日志中这一点会促使 选择 QUERY 而非 GET。
如果服务器创建临时资源来表示 QUERY 请求的结果(例如, 用于 Location 或 Content-Location 字段),为该资源分配 URI,且 请求包含不能记录到日志中的敏感信息,则该 URI 应当选择为不包含原始请求内容中任何敏感部分 的形式。
如果缓存错误地规范化 QUERY 内容,或其规范化方式与 资源处理内容的方式存在显著差异,那么当 规范化造成误匹配时,缓存可能返回不正确的响应。
来自实现了跨源资源共享 (CORS) 的用户代理的 QUERY 请求 将需要“预检”请求,因为 QUERY 不属于 CORS 安全列出的 方法集合(参见 [FETCH])。
5. IANA 注意事项
5.1. QUERY 方法的注册
IANA 已将 QUERY 方法添加到“超文本传输协议 (HTTP) 方法 注册表”,地址为 <http://www.iana.org/assignments/http-methods> (参见 第 16.3.1 节,位于 [HTTP])。
| 方法名 | 安全 | 幂等 | 规范 |
|---|---|---|---|
| QUERY | 是 | 是 | 第 2 节,见 RFC 10008 |
5.2. Accept-Query 字段的注册
IANA 已将 Accept-Query 字段添加到“超文本传输协议 (HTTP) 字段 名注册表”,地址为 <https://www.iana.org/assignments/http-fields> (参见 第 16.1.1 节,位于 [HTTP])。
| 字段名 | 状态 | 结构化类型 | 参考文献 | 备注 |
|---|---|---|---|---|
| Accept-Query | 永久 | List | 第 3 节,见 RFC 10008 |
6. 参考文献
6.1. 规范性参考文献
- [HTTP-CACHING]
- Fielding, R., 编, Nottingham, M., 编, 和 J. Reschke, 编, “HTTP 缓存”, STD 98, RFC 9111, DOI 10.17487/RFC9111, 6 月 2022 年, <https://www.rfc-editor.org/info/rfc9111>.
- [HTTP]
- Fielding, R., 编, Nottingham, M., 编, 和 J. Reschke, 编, “HTTP 语义”, STD 97, RFC 9110, DOI 10.17487/RFC9110, 6 月 2022 年, <https://www.rfc-editor.org/info/rfc9110>.
- [RFC2119]
- Bradner, S., “关键词 用于在 RFC 中指示要求级别”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, 3 月 1997 年, <https://www.rfc-editor.org/info/rfc2119>.
- [RFC8174]
- Leiba, B., “歧义: RFC 2119 关键词中的大写与小写”, BCP 14, RFC 8174, DOI 10.17487/RFC8174, 5 月 2017 年, <https://www.rfc-editor.org/info/rfc8174>.
- [STRUCTURED-FIELDS]
- Nottingham, M. 和 P-H. Kamp, “结构化字段值 用于 HTTP”, RFC 9651, DOI 10.17487/RFC9651, 2024 年 9 月, <https://www.rfc-editor.org/info/rfc9651>.
- [URI]
- Berners-Lee, T., Fielding, R., 和 L. Masinter, “统一资源 标识符 (URI): 通用语法”, STD 66, RFC 3986, DOI 10.17487/RFC3986, 1 月 2005 年, <https://www.rfc-editor.org/info/rfc3986>.
6.2. 资料性参考文献
- [FETCH]
- WHATWG, “FETCH”, WHATWG 现行
标准, <https://fetch.spec.whatwg.org>.
提交 快照: <https://fetch.spec.whatwg.org/commit-snapshots/3bab31a55154bda73f25b45a23df718616f2f64e/>. - [RFC3253]
- Clemm, G., Amsden, J., Ellison, T., Kaler, C., 和 J. Whitehead, “版本控制扩展,用于 WebDAV(Web 分布式创作与版本控制)”, RFC 3253, DOI 10.17487/RFC3253, 3 月 2002 年, <https://www.rfc-editor.org/info/rfc3253>.
- [RFC4918]
- Dusseault, L., 编, “HTTP 扩展,用于 Web 分布式创作与版本控制 (WebDAV)”, RFC 4918, DOI 10.17487/RFC4918, 2007 年 6 月, <https://www.rfc-editor.org/info/rfc4918>.
- [RFC5323]
- Reschke, J., 编, Reddy, S., Davis, J., 和 A. Babich, “Web 分布式创作 与版本控制 (WebDAV) SEARCH”, RFC 5323, DOI 10.17487/RFC5323, 2008 年 11 月, <https://www.rfc-editor.org/info/rfc5323>.
- [RFC6838]
- Freed, N., Klensin, J., 和 T. Hansen, “媒体类型规范 与注册程序”, BCP 13, RFC 6838, DOI 10.17487/RFC6838, 1 月 2013 年, <https://www.rfc-editor.org/info/rfc6838>.
- [RFC8259]
- Bray, T., 编, “该 JavaScript 对象表示法 (JSON) 数据交换格式”, STD 90, RFC 8259, DOI 10.17487/RFC8259, 2017 年 12 月, <https://www.rfc-editor.org/info/rfc8259>.
- [RFC9535]
- Gössner, S., 编, Normington, G., 编, 和 C. Bormann, 编, “JSONPath: 查询 表达式,用于 JSON”, RFC 9535, DOI 10.17487/RFC9535, 2024 年 2 月, <https://www.rfc-editor.org/info/rfc9535>.
- [URL]
- WHATWG, “URL”, WHATWG 现行标准,
<https://url.spec.whatwg.org>.
提交 快照: <https://url.spec.whatwg.org/commit-snapshots/52526653e848c5a56598c84aa4bc8ac9025fb66b/>. - [XSLT]
- Kay, M., 编, “XSL
转换 (XSLT) 3.0 版”, W3C 推荐标准, 2017 年 6 月,
<https://www.w3.org/TR/2017/REC-xslt-30-20170608/>.
最新 版本可通过以下地址获取:https://www.w3.org/TR/xslt-30/。
附录 A. 示例
以下示例仅用于说明;如果需要发送的查询 确实如此简短,那么使用 GET 可能更合适。
大多数示例使用的媒体类型是 "application/x-www-form-urlencoded"(也用于来自浏览器 用户客户端的 POST 请求,定义见 "application/x-www-form-urlencoded" ,位于 [URL])。为简洁起见,已 省略 Content-Length 字段。
A.1. 简单查询
以下是一个具有直接响应的简单查询:
QUERY /contacts HTTP/1.1 Host: example.org Content-Type: application/x-www-form-urlencoded Accept: application/json select=surname,givenname,email&limit=10&match=%22email=*@example.*%22
响应:
HTTP/1.1 200 OK
Content-Type: application/json
[
{ "surname": "Smith",
"givenname": "John",
"email": "smith@example.org" },
{ "surname": "Jones",
"givenname": "Sally",
"email": "sally.jones@example.com" },
{ "surname": "Dubois",
"givenname": "Camille",
"email": "camille.dubois@example.net" }
]
A.2. 发现 QUERY 支持
OPTIONS /contacts HTTP/1.1 Host: example.org
响应:
HTTP/1.1 200 OK Allow: GET, QUERY, OPTIONS, HEAD
Allow 响应字段 (第 10.2.1 节, 见 [HTTP]) 表示 指定资源所支持的方法集合。
除了使用 OPTIONS,还有其他方式。例如,可以在事先不知道服务器是否支持的情况下, 尝试发送 QUERY 请求。服务器随后要么处理该 请求,要么以 4xx 状态响应,例如 405(不允许的方法,第 15.5.6 节, 见 [HTTP]),其中包含 Allow 响应字段。
A.3. 发现 QUERY 格式
可以通过 Accept-Query 响应字段发现 QUERY 支持的媒体类型 (第 3 节):
HEAD /contacts HTTP/1.1 Host: example.org
响应:
HTTP/1.1 200 OK Content-Type: application/xhtml Accept-Query: application/x-www-form-urlencoded, application/sql
哪些请求方法的响应会包含 Accept-Query,取决于 所访问的资源。
除了检查 Accept-Query,还可以发出 QUERY 请求,然后在 收到 4xx 状态时,例如 415 响应(不支持的媒体类型,第 15.5.16 节,见 [HTTP]), 检查 Accept 响应字段 (第 12.5.1 节, 见 [HTTP]):
HTTP/1.1 415 Unsupported Media Type Content-Type: application/xhtml Accept: application/x-www-form-urlencoded, application/sql
A.4. Content-Location、Location 和 间接响应
如第 2.3 节和第 2.4 节所述,成功响应中的 Content-Location 和 Location 响应 字段(2xx,第 15.3 节,见 [HTTP])提供了一种 标识可响应 GET 请求的替代资源的方式,这些资源可以用于获取已收到的 请求结果,也可以用于后续执行相同操作的请求。回到 附录 A.1 中的示例:
QUERY /contacts HTTP/1.1 Host: example.org Content-Type: application/x-www-form-urlencoded Accept: application/json select=surname,givenname,email&limit=10&match=%22email=*@example.*%22
响应:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /contacts/stored-results/17
Location: /contacts/stored-queries/42
Last-Modified: Sat, 25 Aug 2012 23:34:45 GMT
Date: Sun, 17 Nov 2024, 16:10:24 GMT
[
{ "surname": "Smith",
"givenname": "John",
"email": "smith@example.org" },
{ "surname": "Jones",
"givenname": "Sally",
"email": "sally.jones@example.com" },
{ "surname": "Dubois",
"givenname": "Camille",
"email": "camille.dubois@example.net" }
]
A.4.1. 使用 Content-Location
上面收到的 Content-Location 响应字段标识了一个资源, 该资源保存了此字段所在 QUERY 响应的结果:
GET /contacts/stored-results/17 HTTP/1.1 Host: example.org Accept: application/json
响应:
HTTP/1.1 200 OK
Last-Modified: Sat, 25 Aug 2012 23:34:45 GMT
Date: Sun, 17 Nov 2024, 16:10:25 GMT
[
{ "surname": "Smith",
"givenname": "John",
"email": "smith@example.org" },
{ "surname": "Jones",
"givenname": "Sally",
"email": "sally.jones@example.com" },
{ "surname": "Dubois",
"givenname": "Camille",
"email": "camille.dubois@example.net" }
]
请注意,不能保证服务器会无限期地提供此资源, 因此,在收到错误响应后,客户端需要重新执行 原始 QUERY 请求,以获得新的替代位置。
A.4.2. 使用 Location
Location 响应字段标识了一个资源,该资源将响应 GET,返回 与原始 QUERY 请求具有相同处理过程和参数的当前结果。
GET /contacts/stored-queries/42 HTTP/1.1 Host: example.org Accept: application/json
在此示例中,一个条目已于 2024-11-17T16:12:01Z 被移除(如 Last-Modified 字段所示),因此响应仅包含两个条目:
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Sun, 17 November 2024, 16:12:01 GMT
ETag: "42-1"
Date: Sun, 17 Nov 2024, 16:13:17 GMT
[
{ "surname": "Smith",
"givenname": "John",
"email": "smith@example.org" },
{ "surname": "Dubois",
"givenname": "Camille",
"email": "camille.dubois@example.net" }
]
假设服务器仍然公开该资源,且 查询结果未发生变化,则后续包含以下字段的条件 GET 请求:
If-None-Match: "42-1"
将产生 304(未修改)响应 (第 15.4.5 节,见 [HTTP])。
A.4.3. 间接响应
服务器可以发送“间接”响应 (第 2.5 节),使用状态码 303(参见其他,第 15.4.4 节,见 [HTTP])。
对于以下附录开头给出的请求:附录 A.4, 服务器可能响应为:
HTTP/1.1 303 See Other Content-Type: text/plain Date: Sun, 17 Nov 2024, 16:13:17 GMT Location: /contacts/stored-queries/42 请参见 "/contacts/stored-queries/42" 处存储的查询。
这与在直接响应中包含 Location 类似,只是没有返回 查询结果。这使服务器只需生成或复用一个 替代资源。随后可以按照以下方式使用此资源:附录 A.4.2。
A.5. 条件请求
考虑一个实现了 QUERY 的资源,它支持 "application/sql" 和 "application/xslt+xml" [XSLT] 作为请求 媒体类型,并且能够生成 "text/csv" 格式的响应。被查询的数据集 包含 RFC 文档信息,查询返回按十年分组的信息:
QUERY /rfc-index.xml HTTP/1.1 Host: example.org Date: Sun, 7 Sep 2025, 00:00:00 GMT Content-Type: application/xslt+xml Accept: text/csv ...使用 XSLT 的查询内容...
响应:
HTTP/1.1 200 OK Date: Sun, 7 Sep 2025, 00:00:00 GMT Location: /stored-queries/4815162342 Content-Type: text/csv Accept-Query: "application/sql", "application/xslt+xml" Last-Modified: Sun, 31 Aug 2025, 08:44:00 GMT Vary: Accept-Query, Content-Encoding, Content-Type decade, total, with errata, % with errata, average page count 1960, 26, 5, 19.2, 5.3 1970, 666, 18, 2.7, 6.1 1980, 376, 44, 11.7, 23.4 1990, 1593, 269, 16.9, 25.5 2000, 2888, 1048, 36.3, 27.3 2010, 2954, 895, 30.3, 26.1 2020, 1133, 230, 20.3, 26.2
这里,服务器已将路径 "/stored-queries/4815162342" 分配给等价 资源 (第 2.4 节), 以供后续通过 GET 使用。
稍后,客户端重复该查询,但指定仅在结果 发生变化时才返回结果:
QUERY /rfc-index.xml HTTP/1.1 Host: example.org Date: Mon, 8, Sep 2025, 11:00:00 GMT Content-Type: application/sql Accept: text/csv If-Modified-Since: Sun, 31 Aug 2025, 08:44:00 GMT Vary: Accept-Query, Content-Type ...相同的查询,但使用 SQL...
被查询的数据没有变化,因此服务器响应为:
HTTP/1.1 304 Not Modified Date: Mon, 8 Sep 2025, 11:00:00 GMT Content-Type: text/csv Location: /stored-queries/4815162342 Accept-Query: "application/sql", "application/xslt+xml" Last-Modified: Sun, 31 Aug 2025, 08:44:00 GMT Vary: Accept-Query, Content-Type
由于服务器已为等价资源标识了 URI,因此可以 通过 GET 访问该资源。具体而言,这避免了重新发送查询请求的内容:
GET /stored-queries/4815162342 HTTP/1.1 Host: example.org Date: Sun, 21, Sep 2025, 12:08:00 GMT Accept: text/csv If-Modified-Since: Sun, 31 Aug 2025, 00:00:00 GMT
这里,数据集的状态确实发生了变化,因此返回新内容:
HTTP/1.1 200 OK Date: Sun, 21, Sep 2025, 12:08:00 GMT Content-Type: text/csv Last-Modified: Thu, 18 Sep 2025, 19:56:00 GMT Vary: Accept-Query, Content-Encoding, Content-Type decade, total, with errata, % with errata, average page count 1960, 26, 5, 19.2, 5.3 1970, 666, 18, 2.7, 6.1 1980, 376, 44, 11.7, 23.4 1990, 1593, 269, 16.9, 25.5 2000, 2888, 1048, 36.3, 27.3 2010, 2954, 895, 30.3, 26.1 2020, 1133, 230, 20.3, 26.2
(请注意本十年对应行中的变化。)
下图说明了条件请求的用法,以及在 为等价资源分配 URI 时(且客户端利用 该 URI 时)可能产生的差异。虚构的字段名 "Validator" 仅用于演示 目的。
图 1: 仅使用 QUERY 的数据流
图 2: 使用 GET 访问等价资源的数据流
A.6. 更多查询格式
以下示例展示了对 JSON 形式的 [RFC8259] RFC 勘误数据库的请求。
以下请求使用可扩展样式表语言转换 (XSLT) 来提取 按年份和已定义的勘误类型汇总的勘误信息。
QUERY /errata.json HTTP/1.1
Host: example.org
Content-Type: application/xslt+xml
Accept: application/xml, text/csv
<transform xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:j="http://www.w3.org/2005/xpath-functions"
version="3.0">
<output method="text"/>
<param name="input"/>
<variable name="json"
select="json-to-xml(unparsed-text($input))"/>
<variable name="sc">errata_status_code</variable>
<variable name="sd">submit_date</variable>
<template match="/">
<text>year, total, rejected, verified, hdu, reported</text>
<text> </text>
<variable name="en" select="$json//j:map"/>
<for-each-group select="$en"
group-by="substring-before(j:string[@key=$sd],'-')">
<sort select="current-grouping-key()"/>
<variable name="year" select="current-grouping-key()"/>
<variable name="errata" select=
"$en[$year=substring-before(j:string[@key=$sd],'-')]"/>
<value-of select="concat(
$year,
', ',
count($errata),
', ',
count($errata['Rejected'=j:string[@key=$sc]]),
', ',
count($errata['Verified'=j:string[@key=$sc]]),
', ',
count(
$errata['Held for Document Update'=j:string[@key=$sc]]),
', ',
count($errata['Reported'=j:string[@key=$sc]]),
' ')"/>
</for-each-group>
</template>
</transform>
响应:
HTTP/1.1 200 OK Content-Type: text/csv Accept-Query: "application/jsonpath", "application/xslt+xml" Date: Wed, 19 Feb 2025, 17:10:01 GMT year, total, rejected, verified, hdu, reported 2000, 14, 0, 14, 0, 0 2001, 72, 1, 70, 1, 0 2002, 124, 8, 104, 12, 0 2003, 63, 0, 61, 2, 0 2004, 89, 1, 83, 5, 0 2005, 156, 10, 96, 50, 0 2006, 444, 54, 176, 214, 0 2007, 429, 48, 188, 193, 0 2008, 423, 52, 165, 206, 0 2009, 331, 39, 148, 144, 0 2010, 538, 80, 232, 222, 4 2011, 367, 47, 170, 150, 0 2012, 348, 54, 149, 145, 0 2013, 341, 61, 169, 106, 5 2014, 342, 73, 180, 72, 17 2015, 343, 79, 145, 89, 30 2016, 295, 46, 122, 82, 45 2017, 303, 46, 120, 84, 53 2018, 350, 61, 118, 98, 73 2019, 335, 47, 131, 94, 63 2020, 387, 68, 117, 123, 79 2021, 321, 44, 148, 63, 66 2022, 358, 37, 198, 40, 83 2023, 262, 38, 121, 33, 70 2024, 322, 33, 125, 23, 141 9999, 1, 0, 0, 1, 0
请注意,Accept-Query 响应字段表明还支持另一种查询格式 JSONPath [RFC9535], 同样受到支持。以下请求将报告所有自 2024 年以来提交的 已拒绝勘误的标识符:
QUERY /errata.json HTTP/1.1
Host: example.org
Content-Type: application/jsonpath
Accept: application/json
$..[
?@.errata_status_code=="Rejected"
&& @.submit_date>"2024"
]
["doc-id"]
响应:
HTTP/1.1 200 OK Content-Type: application/json Accept-Query: "application/jsonpath", "application/xslt+xml" Date: Thu, 20 Feb 2025, 09:55:42 GMT Last-Modified: Thu, 20 Feb 2025 06:10:01 GMT [ "RFC1185","RFC8407","RFC6350","RFC8467","RFC1157","RFC9543", "RFC9076","RFC7656","RFC2822","RFC9460","RFC2104","RFC6797", "RFC9499","RFC9557","RFC2131","RFC2328","RFC9001","RFC3325", "RFC9438","RFC2526","RFC2985","RFC7643","RFC9132","RFC6376", "RFC9110","RFC9460","RFC7748","RFC9497","RFC8463","RFC4035", "RFC7239","RFC9083","RFC9537","RFC9537","RFC9420","RFC9000", "RFC9656","RFC9110","RFC2324","RFC2549","RFC6797","RFC2549", "RFC8894" ]
附录 B. 方法名 'QUERY' 的选择
“超文本传输协议 (HTTP) 方法注册表” (<http://www.iana.org/assignments/http-methods>) 已包含另外三个具有“安全”和“幂等”属性的方法:"PROPFIND" [RFC4918]、 "REPORT" [RFC3253], 以及 "SEARCH" [RFC5323]。
原本可以复用其中任意一个方法,通过更新使其符合 本规范定义的新方法 "QUERY"。事实上,本 规范在早期阶段曾使用 "SEARCH"。
最终选择方法名 "QUERY" 的原因如下:
- 其他方法为请求内容使用通用媒体类型 ("application/xml"); 请求的语义完全取决于请求内容。
- 此外,它们都源自 WebDAV 活动,而许多人对此抱有复杂的 感受。
- "QUERY" 很好地体现了与 URI 查询组件之间的关系。
致谢
我们感谢 HTTP 工作组的所有成员提出的想法、审查意见和反馈。
以下人员值得特别感谢:Carsten Bormann、Mark Nottingham、 Martin Thomson、Michael Thornburgh、Roberto Polli、Roy Fielding 和 Will Hawkins。
贡献者
Ashok Malhotra 参与了促成本规范的早期讨论:
电子邮件: malhotrasahib@gmail.com
Asbjørn Ulsberg 在 HTTP 研讨会期间重新开启了有关此 HTTP 方法的讨论, 时间为 2019 年:
电子邮件: asbjorn@ulsberg.no
URI: https://asbjor.nu/