我正在为我们的应用程序开发一个新的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中使用有效负载。

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

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

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

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

根据RFC 2616第4.3节“消息正文”:

服务器应读取并转发任何请求的消息体;如果请求方法不包括实体实体的定义语义,则在处理请求时应忽略消息体。

也就是说,服务器应该始终从网络中读取任何提供的请求体(检查内容长度或读取分块体等)。此外,代理应该转发他们收到的任何此类请求。然后,如果RFC为给定方法的主体定义了语义,那么服务器实际上可以使用请求主体来生成响应。然而,如果RFC没有定义主体的语义,那么服务器应该忽略它。

这与上面Fielding的引用一致。

第9.3节“GET”描述了GET方法的语义,没有提到请求体。因此,服务器应该忽略它在GET请求中收到的任何请求体。

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

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

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

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

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

哪个服务器会忽略它?–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请求。