RFC 10008:新的 HTTP Query 方法

QUERY 的目的与语义

  • 引入 QUERY 作为“带请求体的 GET”:只读、安全、幂等。
  • 主要目标:支持复杂/大型查询(例如 GraphQL、丰富过滤条件、图片),而不受 URL 长度限制。
  • 仅用于数据检索;语义类似 GET,但请求参数放在请求体中。

缓存、幂等性与安全性

  • 由于 QUERY 是安全且幂等的,中间件和客户端可以像处理 GET 一样自动缓存和重试它,而不是像 POST 那样。
  • 关于缓存键存在争议:
    • 担忧:将整个请求体用作缓存键会产生无上限、由用户控制的键,以及复杂性(顺序、规范化、哈希)。
    • 反驳:这只是可选项;缓存可以对请求体进行哈希,或者更好地,服务器可以返回一个简短的 Location URL,然后再通过 GET 进行缓存。
  • 日志记录和配额等副作用在 HTTP 语义层面被视为“忽略”,与 GET 相同。

GET-with-body 与新方法

  • 有人认为规范应直接标准化 GET 的请求体。
  • 另一些人指出,许多代理/服务器会忽略、丢弃或拒绝 GET 请求体,而且长期以来都不建议这样做,因此事后补加语义并不安全。
  • 新方法可以避免静默篡改:不支持 QUERY 的实现通常会明确失败(例如 405),而不是丢弃数据。

中间件与兼容性

  • 担忧:许多中间盒历史上会错误处理未知方法,或处理它们不理解的任何带请求体的方法。
  • 如果没有广泛的网关/CDN 支持,对于某些场景来说,POST 加自定义头仍然是务实选择。
  • QUERY 还必须处理 CORS:目前不在 safelisted 范围内,因此浏览器即使它是安全的也会进行预检。

用例与开发者反应

  • 建议用途:大型 GraphQL 查询、复杂搜索过滤、dry-run 与 commit 模式(先 QUERY 再 POST)、类似数据库的查询、带事件流的流式 AI 查询。
  • 有些人认为这为“POST /search”这类变通方案提供了清晰的语义修复,并且更符合 HTTP 的方法模型。
  • 怀疑者认为这过于复杂:增加了复杂度、新的基础设施,以及开发者还必须学习的又一个细微差别,而现有 GET/POST 对这个问题已经“足够好”。

HTML 表单、书签与用户体验

  • 有人对 HTML 表单中的 method="query" 很感兴趣,以避免“重新提交 POST 数据”的警告,并更好地映射到安全操作。
  • 更广泛的诉求是让表单使用更多 HTTP 动词(PUT/DELETE 等),以使人类交互与 REST 语义保持一致。
  • 如果查询参数放在请求体中,会影响可收藏书签性;讨论中的缓解方式包括服务器生成 GET URL。

命名与概念争论

  • 有些人觉得 “QUERY” 容易与现有的 “query string” 术语混淆。
  • 少数人认为 HTTP 动词不应该编码业务语义,把这看作是 REST 驱动的过度设计;另一些人则反驳说,HTTP 一直都把语义附加到方法上。