如http://www.boutell.com/newfaq/misc/urllength.html中所述,HTTP查询字符串的长度有限。它可能受客户端(Firefox,IE,...),服务器(Apache,IIS,...)或网络设备(应用防火墙......)的限制。
今天我用搜索表单来解决这个问题。我们开发了一个包含很多字段的搜索表单,这个表单作为GET请求发送到服务器,因此我可以将结果页面添加为书签。
我们有很多字段,我们的查询字符串长度为1100字节,我们有一个防火墙可以丢弃超过1024字节的HTTP GET请求。我们的系统管理员建议我们使用POST,这样就不会有任何限制。
当然,POST会起作用,但我真的觉得搜索是GET而不是POST。所以我想我会查看我们的字段名称,以确保查询字符串不会太长,如果我不能,我会务实并使用POST。
但RESTful服务的设计是否存在缺陷?如果我们在GET请求中的长度有限,我该如何将大对象发送到RESTful Web服务?例如,如果我有一个基于文件进行计算的程序,并且我想提供这样的RESTful Web服务:http://compute.com?content=<base64 file>
。这不起作用,因为查询字符串的长度不限。
我有点困惑......
答案 0 :(得分:57)
HTTP规范实际上advises to use POST when sending data to a resource用于计算。
您的搜索看起来像计算,而不是资源本身。如果您仍希望搜索结果成为资源,您可以执行的操作是创建一个令牌来标识该特定搜索结果,并将用户代理重定向到该资源。
然后,您可以在一段时间后删除搜索结果标记。
示例强>
POST /search
query=something&category=c1&category=c2&...
201 Created
Location: /search/01543164876
然后
GET /search/01543164876
200 Ok
... your results here...
这样,浏览器和代理仍然可以缓存搜索结果,但您使用POST提交查询参数。
编辑
为了澄清,此处01543164876
表示代表您的搜索的资源的唯一ID。这两个请求基本上是指:使用这些条件创建一个新的搜索对象,然后检索与创建的搜索对象关联的结果。
此ID可以是为每个新请求生成的唯一ID。这意味着您的服务器将泄漏“搜索”对象,您将不得不使用缓存策略定期清理它们。
或者它可以是实际代表用户询问的搜索的所有搜索条件的散列。这允许您重用ID,因为重新创建搜索将返回可能(或可能不)已缓存的现有ID。
答案 1 :(得分:50)
根据您的描述,恕我直言,您应该使用POST。 POST用于将数据放在服务器上,在某些情况下,可以获得答案。在您的情况下,您进行搜索(向服务器发送查询)并获取该搜索的结果(检索查询结果)。
GET的定义说它必须用于检索已经存在的资源。根据定义,POST是创建一个新资源。这正是您正在做的事情:在服务器上创建资源并检索它!即使您不存储搜索结果,您也在服务器上创建了一个对象并将其检索出来。正如PeterMmm先前所说的那样,你可以通过POST(创建并存储查询结果)来执行此操作,然后使用GET来检索查询,但是只做POST并检索结果更实际。
希望这有帮助! :)
答案 2 :(得分:5)
REST是一种做事的方式,而不是协议。即使你不喜欢POST,当它真的是一个GET时,它也会起作用。
如果您将/必须保持GET,POST等的“标准”定义,而不是考虑POST查询,那么该查询将存储在具有查询ID的服务器上,并稍后通过GET请求查询标识。
答案 3 :(得分:5)
围绕GET的混淆是浏览器限制。如果要为A2A或P2P应用程序创建RESTful接口,则对GET的长度没有限制。
现在,如果您碰巧想要使用浏览器来查看您的RESTful界面(也就是在开发/调试期间),那么您将遇到这个限制,但是有一些工具可以解决这个问题。
答案 4 :(得分:3)
关于你的例子:http://compute.com?content={base64file}
,我会使用POST,因为你要上传要计算的“东西”。对我来说,这个“东西”感觉更像是一个简单的参数资源。
与通常的搜索相反,我会开始坚持使用GET和参数。你让api-clients更容易测试和玩你的api。使只读访问(在大多数情况下是大多数流量)尽可能简单!
但是大型查询字符串的困境是GET的有效限制。在这里我会务实,只要你没有达到这个限制,请使用GET和url-params。这将适用于98%的搜索案例。只有在达到此限制时才会执行,然后还会引入带有效负载的POST(使用mime-type Content-Type: application/x-www-form-urlencoded
)。
你有更多现实世界的例子吗?
答案 5 :(得分:0)
5年后,似乎存在另一个可行的选择 - 使用GET
的邮件正文。我将这个答案作为上述所有建议的替代方案,尽管它有其自身的局限性(做一些研究)。
答案 6 :(得分:0)
这很简单。使用POST。 HTTP不对GET的URL长度施加限制,但服务器会这样做。务实,并通过POST解决这个问题。
你也可以使用GET主体(这是允许的),但这是一个双重打击,因为它使用不正确,可能会出现服务器问题。