摘要

  • QUERY 用请求内容承载查询表达式,并被注册为安全且幂等的方法。这是一项实现义务,不是对任意处理器“没有业务副作用”的自动认证。
  • 请求内容及其元数据必须进入缓存键。重试、重定向、条件请求、Accept-Query 与等价资源 URI 分别配置客户端、缓存和源站的权力;内容离开 URI 也不等于获得保密性。

设想一个数据平台要接收带有嵌套条件、字段投影和排序逻辑的查询。GET 适合读取,但 RFC 9110 没有为 GET 所收到的请求内容规定通用语义,部分实现甚至会拒绝它。POST 可以自然携带内容,可一旦连接在上传后断开,客户端不能仅凭方法判断再次发送会不会重复一项业务动作。

2026 年 6 月发布、状态为 Proposed Standard 的 RFC 10008 在这条缝隙中定义了 QUERY。它要求请求必须有内容,媒体类型说明查询采用何种表达格式,内容和相关元数据共同定义向目标资源提出的问题。IANA 已把 QUERY 登记为 safe=yes、idempotent=yes,也把 Accept-Query 登记为永久 HTTP 字段。

它不是“带 body 的 GET”,也不是换了名字的 POST。“安全”表示调用者所请求的语义是读取,而非改变业务状态;“幂等”表示重复同一请求的预期效果与执行一次相同,并不保证每次返回相同字节。若处理器会扣费、占用席位、消耗一次性资格、批准交易或轮换凭据,即使程序能防止第二次重复,它仍然不是一项安全查询。

方法属性是给其他参与者的依赖许可

安全与幂等之所以重要,在于别人会据此行动。客户端可能自动发起安全读取;传输库可能在“不知道第一次是否执行”的故障后重试幂等方法;缓存只会对自己理解的方法建立存储与复用规则。源站暴露 QUERY,也就允许这些角色依赖自己的承诺。

因此,路由注解和 API 文档只能证明声明,不能证明结果。有效证据要把方法、内容与媒体类型的精确指纹、身份上下文、应用执行记录、副作用以及最终表征串在一起。发生重试时,必须回答:第一次是否到达业务逻辑?第二次是否产生了任何不应发生的变化?

技术日志可以是读取附带的观测;但扣减额度、推动业务游标、创建审批或发出外部命令,是用户所请求的后果。合规判断应跟随后果,而不是跟随函数名。

内容不是缓存身份之外的货物

RFC 10008 最关键的要求之一,是 QUERY 的缓存键必须包含请求内容和相关内容元数据。同一方法、同一 URI、不同查询体,仍是不同问题。只以方法和 URI 建键,可能把甲的筛选结果交给乙。

为了计算完整键,缓存可能必须先读完全部内容。原先可以边收边转发的路径,开始承担缓冲、内存、时延与反压成本。因此,最大内容尺寸、读取超时和流式处理边界都是部署设计,而非实现末节。

理解媒体类型的缓存可以规范化真正不影响语义的差异。例如某种格式明确允许忽略空白。但“可以规范化”本身就是一项语义权力:若数组顺序有意义,排序就会把两个不同问题合并;若数字表达或 Unicode 处理不一致,也会出现错误命中。Cache-Control: no-transform 是协议指令,却不是“任何层都没有转换过缓存键材料”的审计证明。

测试必须同时寻找两类错误:同一含义的不同写法未能复用,以及不同含义的相似写法被错误合并。重复字段、默认值、数字精度、Unicode 规范化、内容编码、签名输入和授权分区都应进入样本。在所有解析器共享可靠的规范化规则以前,保留差异只会少一些命中;虚构同一性可能泄露或篡改结果。

给结果命名,会改变它的治理寿命

RFC 10008 所说的等价资源,由目标资源、QUERY 内容及相关元数据共同导出。源站可以给它分配 URI,让后续读取改用 GET。一次临时表达式由此获得可复制、可缓存、可长期引用的名称。

Location 与 Content-Location 不能混为一个“规范链接”。成功的 QUERY 响应中,Location 可以指向以后用 GET 获取的等价资源或查询资源;Content-Location 则按 HTTP 语义标识当前返回表征对应的 URI。客户端若把二者统一处理,就抹去了源站究竟命名了“资源”还是“返回表征”的声明。

命名也可能重新暴露内容。若生成的 URI 含有账户标识、诊断条件或机密筛选器,原本移出 GET 地址的数据又进入浏览历史、访问日志、引用和分享界面。使用不透明标识可以减少这一风险,却引入有效期、授权、撤销和可猜测性问题。一个稳定 URI 可能活得比首次执行它的权限上下文更久。

RFC 3986 规范标识符语法,但不会替源站决定名称应当公开多久、是否可转让。命名者拥有权力,也拥有泄露与持久化后果。

重定向状态码决定方法的去向

RFC 10008 对常见歧义作了清楚处理:301、302、307、308 保留 QUERY,历史上 POST 可能转为 GET 的例外不适用;303 才明确要求改用 GET。前一组会把方法及其内容送往新目标,后一种指向可读取资源。

如果网关沿用旧习惯把 QUERY 改成 GET,查询内容可能丢失,或被重新塞回 URI;改成 POST 则撤销了客户端据以重试的语义。每一种状态码、跨源跳转、凭据剥离与内容尺寸都要单独验证,不能把“跟随重定向”视为一项通用功能。

条件 QUERY 也有精确的参照物:验证器针对的是“对等价资源执行 GET 时本会选中的表征”。内容协商、身份与授权仍影响选择。请求体哈希不能自动成为结果表征的验证器。

Accept-Query 是有范围、有时效的能力证据

Accept-Query 使用 RFC 9651 的 Structured Fields List 公告可接收的媒体类型。其适用范围覆盖相同 path、忽略 URI query component 的资源;存在多个观察值时,采用最近且仍然新鲜的值。

它不证明任意表达式都有效,也不证明每个部署节点或中间设备都支持 QUERY 缓存。审计要记录产生字段的响应、path、鲜度和节点版本,滚动发布时尤其如此。

浏览器还有一层现实边界。Fetch Standard 的 CORS safelisted methods 只有 GET、HEAD、POST,不含 QUERY。跨源使用必须预检。应用层即使实现正确,也可能被网关、WAF 或 CORS 配置拒绝。

离开 URI,不代表离开数据链

QUERY 可以减少复杂条件进入 URI 专用日志、复制链接和地址长度限制,这是实在的架构收益。但内容仍经过客户端、浏览器开发工具、TLS 终止点、网关、缓存、追踪系统和源站,也可能被采样、记录或保留。重试会再次发送;重定向会改变接收者;错误设计的等价 URI 会把它永久公开。

Lu Heng 对数据主权的技术形式与实践现实的区分,恰好解释这里的权力分散:源站形式上定义查询语言,实际保管者却包括每一个收到内容或其指纹的参与者。只把源站写进数据地图,描述的是规范,不是运行路径。

他的最小初始规范、局部未来决策与自愿采用原则,则说明为什么标准只规定有限共享层:方法、属性、缓存义务、重定向和能力公告。每个源站自行决定查询语言、资源语义与命名;客户端决定是否发出或重试;缓存只有在能保持身份时才自愿复用。

运行代码优先给出最后的举证规则。RFC 能证明各方应当遵守什么;只有执行证据能证明处理器确实安全、重试确实幂等、缓存键确实完整、名称确实没有泄露内容。