返回

文章详情

新HTTP QUERY方法的解释

Hacker News2026年6月23日 06:05

在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作为方法。大多数代理、防火墙和Web服务器仅允许“标准”HTTP方法。那么,为什么在我们已经有一套行之有效的现有方法的情况下引入一个新HTTP方法呢?使用GET的查询​ 传统上,如果你想要过滤一个资源,你会在GET请求中使用查询参数(例如,/api/v1/users?role=admin&status=active&sort=desc)。这对简单过滤效果很好。然而,当你需要执行复杂的关系查询、深层嵌套或高级逻辑时,URL变得庞大、难以阅读,有时会超过浏览器或服务器的字符限制。其他潜在问题包括:发送非ASCII或特殊字符作为参数需要对其进行编码,增加请求大小;服务器和其他中间件可能会记录请求参数,在某些情况下可能会出现问题;表达某些数据结构(如数组)并不规范且具体实现相关(例如,?roles[0]=admin&roles[1]=reporter与?roles=admin&roles=reporter与?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方法了)。其他客户端、代理和Web服务器仍可能拒绝它。标准的GET查询在URL参数中带数据依然完全可行。如果没有立即必要将这些更改为QUERY方法,就保持现状。如果你的用户应该能够分享或书签过滤后的数据,继续使用GET请求。作为QUERY请求分享链接是不可行的。为QUERY实现自定义缓存

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡