我正在为我们的应用程序开发一个新的RESTful Web服务。

当对某些实体执行GET时,客户端可以请求实体的内容。如果他们想添加一些参数(例如排序列表),可以在查询字符串中添加这些参数。

或者,我希望人们能够在请求主体中指定这些参数。HTTP/1.1似乎并没有明确禁止这一点。这将允许他们指定更多信息,可能会更容易指定复杂的XML请求。

我的问题:

这完全是个好主意吗?HTTP客户端在GET请求中使用请求体时会遇到问题吗?

https://www.rfc-editor.org/rfc/rfc2616


当前回答

你可以用身体发送GET,也可以发送POST,然后放弃RESTish宗教信仰(这并不是很糟糕,5年前只有一个信仰的成员——他在上面的评论)。

这两个都不是很好的决定,但发送GET主体可能会防止某些客户端和某些服务器出现问题。

进行POST可能会遇到一些RESTish框架的障碍。

Julian Reschke在上文中建议使用非标准HTTP头,如“SEARCH”,这可能是一个很好的解决方案,只是它不太可能被支持。

列出能够和不能做到上述每一项的客户可能是最有成效的。

无法发送带有正文的GET的客户端(我知道):

XmlHTTPRequest Fiddler

可以发送带有正文的GET的客户端:

大多数浏览器

可以从GET检索正文的服务器和库:

阿帕奇PHP文件

从GET中剥离主体的服务器(和代理):

?

其他回答

您试图实现的目标已经用一种更常见的方法完成了很长时间,这种方法不依赖于在GET中使用有效负载。

您可以简单地构建特定的搜索中介类型,或者如果您希望更具RESTful,可以使用类似OpenSearch的方法,并将请求POST到服务器指示的URI,例如/search。然后,服务器可以生成搜索结果或构建最终URI并使用303重定向。

这具有遵循传统PRG方法的优点,有助于缓存中介缓存结果等。

也就是说,URI无论如何都是针对非ASCII的任何内容进行编码的,application/x-www-form-urlencoded和multipart/form数据也是如此。如果您打算支持ReSTful场景,我建议使用此格式,而不是创建另一种自定义json格式。

即使一个流行的工具使用了这个,正如本页经常引用的,我认为这仍然是一个非常糟糕的主意,因为它太奇特了,尽管规范没有禁止。

许多中间基础设施可能只是拒绝这样的请求。

例如,忘记在网站前面使用一些可用的CDN,如下图所示:

如果查看器GET请求包含正文,CloudFront将向查看器返回HTTP状态代码403(禁止)。

是的,您的客户端库也可能不支持发出这样的请求,如本文评论中所述。

虽然您可以做到这一点,但只要HTTP规范没有明确排除它,我建议避免它,因为人们不希望事情以这种方式工作。HTTP请求链中有许多阶段,虽然它们“大部分”符合HTTP规范,但唯一可以保证的是,它们的行为将与web浏览器传统使用的一样。(我想的是透明代理、加速器、A/V工具包等)

这就是稳健性原则背后的精神。大致上,“接受的内容要自由,发送的内容要保守”,你不想在没有充分理由的情况下突破规范的界限。

然而,如果你有充分的理由,那就去做吧。

如果您真的想将可计算的JSON/XML正文发送到web应用程序,那么放置数据的唯一合理位置是使用RFC4648:Base64Encoding和URL和文件名安全字母表编码的查询字符串。当然,您可以只对JSON进行URL编码,并将其放入URL参数的值中,但Base64给出的结果较小。请记住,URL大小有限制,请参阅不同浏览器中URL的最大长度是多少。

您可能会认为Base64的padding=字符可能对URL的参数值有害,但这似乎不是-请参阅以下讨论:http://mail.python.org/pipermail/python-bugs-list/2007-February/037195.html . 但是,您不应该将编码数据放在没有参数名称的位置,因为带填充的编码字符串将被解释为具有空值的参数键。我会用类似的东西_b64=<编码器数据>。

关于一个老问题的想法:

在正文中添加完整的内容,在查询字符串中添加正文的短哈希,这样缓存就不会有问题(如果正文内容发生变化,哈希值会发生变化),并且您可以在需要时发送大量数据:)