开发者生态
morning
新的 HTTP QUERY 方法解释
2026-06-23
1 阅读
CommonGuy
在 RESTful API 的世界中,我们长期以来一直遵循一套严格的(自我强加的)规则。无论您是使用 GET 获取数据、使用 POST 创建实体还是使用 PUT 更新资源,HTTP 方法都会告诉服务器您的意图。最近,RFC 10008 发布,它定义了 HTTP 的新 QUERY 方法。当我们已经有其他 HTTP 方法时,为什么还需要这个?让我们来看看吧。从纯粹的技术角度来看,HTTP 方法只是一个字符串。理论上,您也可以使用 FETCH /api/v1/users,而不是发送 GET /api/v1/users。实际上,围绕众所周知的 HTTP 方法(例如 GET 和 POST)存在大量 RFC 和隐式的、未记录的行为。例如,当您输入地址或单击书签时,浏览器会发送 GET 请求。标准 HTTP 表单仅允许 GET 和 POST 作为方法。大多数代理、防火墙和网络服务器只允许“标准”HTTP 方法。那么,当我们已经拥有一组运行良好数十年的现有方法时,为什么要引入新的 HTTP 方法呢?使用 GET 进行查询 传统上,如果您想过滤资源,可以在 GET 请求中使用查询参数(例如 /api/v1/users?role=admin&status=active&sort=desc )。这对于简单的过滤器非常有效。然而,当您需要执行复杂的关系查询、深层嵌套或高级逻辑时,URL 会变得庞大、难以阅读,有时会达到浏览器或服务器字符限制。其他潜在问题包括: 发送非 ASCII 或特殊字符作为参数需要对其进行编码,从而增加请求大小 服务器和其他中间件可能会记录请求参数,这在某些情况下可能会出现问题 表达某些数据结构(例如数组)没有明确定义且特定于实现(例如 ?roles[0]=admin&roles[1]=reporter vs ?roles=admin&roles=reporter vs ?roles[]=admin&roles[]=reporter ) 与表达深层嵌套结构相同 既然这些都是将数据作为查询参数发送的缺点,为什么不简单地发送带有 JSON 请求正文的 GET 请求呢?同样,从理论角度来看,这应该可行。没有任何 HTTP RFC 明确禁止在执行 HTTP GET 请求时使用请求正文,但指出不应这样做。因此,各种客户端、代理和 Web 服务器实现以不同的方式处理带有正文的 GET 请求。有些人直接拒绝它们,有些人干脆放弃尸体,而另一些人则解释它。因此,将 HTTP GET 与请求正文结合使用是一个坏主意,例如,位于公司防火墙或其他浏览器后面的用户可能无法使用您的网站。这也是为什么没有新的 RFC 指定 GET 请求现在应该支持请求正文的原因,因为这会破坏许多现有的实现。解决方法:使用 POST 查询由于使用 GET 发送请求正文可能会带来问题,因此解决方法是使用 POST。虽然 POST 允许请求正文,但它引入了重大的语义问题。 POST 被定义为非幂等的,旨在用于资源创建或处理。虽然这听起来可能不是一个大问题,但在实施时可能会很烦人。失败时自动重试。由于 GET 方法被定义为安全且幂等的,只要服务器实现正确,我们就可以重试失败的请求,而不必担心副作用。它还使得代理或其他中间件无法自动理解该操作是只读的。例如,中间件可能会自动将 GET 请求缓存一段时间,这不适用于 POST 请求。 QUERY 方法 所有上述原因导致经过多年的讨论后,指定了 QUERY 方法。 QUERY 方法没有什么特别的,RFC 粗略地指出它与 GET 方法类似,但带有请求正文。它应该是安全且幂等的。 QUERY请求可以被缓存,但是实现时必须小心地将请求内容合并到缓存键中。总而言之,它最终为复杂的搜索查询提供了一个合适的 HTTP 方法。 QUERY 陷阱 立即将所有搜索相关端点切换为使用 QUERY 可能很诱人。在此之前,您需要考虑一些事项。对 HTTP QUERY 的支持仍然非常有限,并且可能会持续一段时间。可能需要数年时间才能在各地得到充分支持。例如,Kreya 在最近的 1.20 版本中添加了对 HTTP QUERY 的开箱即用支持(尽管之前已经可以发送自定义 HTTP 方法)。其他客户端、代理和网络服务器可能仍会拒绝它。在 URL 参数中包含数据的标准 GET 查询仍然完全没问题。如果不需要立即将它们更改为 QUERY 方法,则保留它们。如果您的用户应该能够共享已过滤数据的链接或为其添加书签,请继续使用 GET 请求。作为 QUERY 请求共享链接不起作用。为 QUE 实现自定义缓存