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

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

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

我的问题:

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

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


当前回答

Elasticsearch接受带有主体的GET请求。甚至似乎这是首选的方法:Elasticsearch指南

一些客户端库(如Ruby驱动程序)可以在开发模式下将cry命令记录到stdout,并且它广泛使用这种语法。

其他回答

罗伊·菲尔丁(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请求上发送有效负载主体可能会导致一些现有实现拒绝该请求。

如果您尝试利用缓存,可能会遇到问题。代理不会在GET主体中查看参数是否对响应有影响。

如果您希望允许带有主体的GET请求,一种方法是支持带有标题“X-HTTP-Method-Override:GET”的POST请求。此处描述如下:https://en.wikipedia.org/wiki/List_of_HTTP_header_fields.这个头意味着当方法是POST时,应该将请求视为GET。POST允许Body,因此您可以确定没有人会丢弃GET请求的有效负载。

此标头通常用于通过一些不识别这些方法的代理生成PATCH或HEAD请求,并用GET替换它们(调试总是很有趣!)。

关于一个老问题的想法:

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

例如,它适用于Curl、Apache和PHP。

PHP文件:

<?php
echo $_SERVER['REQUEST_METHOD'] . PHP_EOL;
echo file_get_contents('php://input') . PHP_EOL;

Console命令:

$ curl -X GET -H "Content-Type: application/json" -d '{"the": "body"}' 'http://localhost/test/get.php'

输出:

GET
{"the": "body"}