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

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

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

我的问题:

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

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


当前回答

哪个服务器会忽略它?–2012年8月30日21:27

例如,谷歌做得比忽视它更糟糕,它会认为这是一个错误!

用一个简单的netcat自己试试:

$ netcat www.google.com 80
GET / HTTP/1.1
Host: www.google.com
Content-length: 6

1234

(1234内容后面是CR-LF,总共6个字节)

你会得到:

HTTP/1.1 400 Bad Request
Server: GFE/2.0
(....)
Error 400 (Bad Request)
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know.

您还可以从Bing、Apple等获得400个Bad Request,这些请求由AkamaiGhost提供。

因此,我不建议对主体实体使用GET请求。

其他回答

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

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

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

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

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

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

XmlHTTPRequest Fiddler

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

大多数浏览器

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

阿帕奇PHP文件

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

?

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

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

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

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

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

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

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

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

我不建议这样做,这违背了标准做法,也没有提供那么多回报。您希望保留内容的正文,而不是选项。

罗伊·菲尔丁(Roy Fielding)关于在GET请求中包含身体的评论。

对换句话说,任何HTTP请求消息都允许包含消息体,因此必须考虑到这一点来解析消息。然而,GET的服务器语义受到限制,使得主体(如果有的话)对请求没有语义意义。解析的需求与方法语义的需求是分开的。所以,是的,你可以用GET发送一个身体,但不,这样做从来都没有用。这是HTTP/1.1分层设计的一部分,一旦规范被划分(正在进行中),分层设计将再次变得清晰。……罗伊

是的,您可以用GET发送请求体,但它应该没有任何意义。如果您通过在服务器上解析它并根据其内容更改响应来赋予其含义,那么您将忽略HTTP/1.1规范第4.3节中的建议:

…如果请求方法不包含实体体的定义语义,则在处理请求时应忽略消息体。

以及HTTP/1.1规范第9.3节中GET方法的描述:

GET方法意味着检索请求URI标识的任何信息([…])。

其声明请求主体不是GET请求中的资源标识的一部分,而是请求URI。

使现代化

被称为“HTTP/1.1规范”的RFC2616现在已经过时。2014年,它被RFC7230-7237取代。引号“处理请求时应忽略消息正文”已删除。现在只是“请求消息框架独立于方法语义,即使该方法没有定义消息体的任何用途”第二个引号“GET方法意味着检索任何信息……由请求URI标识”被删除。-来自评论

根据HTTP 1.1 2014规范:

GET请求消息中的有效负载没有定义的语义;在GET请求上发送有效负载主体可能会导致一些现有实现拒绝该请求。