我该如何处理HTTP GET查询字符串的长度限制,并且仍然希望成为RESTful?


84

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>。这将不起作用,因为查询字符串没有无限的长度。

我有点困惑


2
在您的上下文中,宁静是什么意思?或释义:为什么GET宁静而POST却不宁静?因为可以使用简单的字符串连接构造GET?查询长度限制是为了避免在旨在快速运行的应用程序中动态分配内存。
卡其奇

5
当我想搜索时,我不想创建,删除或更新某些东西,我只想检索数据,所以我不应该使用POST,DELETE或PUT,而应该使用GET。这就是我对REST的理解,但我可能对此感到误解
cbliard 2010年

GET不适合搜索,因为搜索结果可能会随时间变化。Web基础结构通常允许缓存GET请求。如果使用GET,则有可能会获得旧的过时搜索结果。POST是一种方式,如下所示。
occulus

15
一切都会随着时间变化(en.wikipedia.org/wiki/Impermanence),这就是宇宙的本质...但是GET应该用于搜索,因为“搜索操作”不会改变结果
Luxspes 2012年

Answers:


51

根据您的描述,恕我直言,您应该使用POST。POST用于将数据存储在服务器上,并且在某些情况下可以获得答案。在您的情况下,您进行搜索(将查询发送到服务器)并获取该搜索的结果(获取查询结果)。

GET的定义说必须使用它来检索已经存在的资源。根据定义,POST是用于创建新资源。这正是您正在执行的操作:在服务器上创建资源并对其进行检索!即使不存储搜索结果,您也可以在服务器上创建一个对象并进行检索。正如PeterMmm先前所言,您可以使用POST(创建并存储查询结果)来执行此操作,然后使用GET来检索查询,但更实际的做法是仅执行POST并检索结果。

希望这可以帮助!:)


2
没错,我可以将其视为POST,因为搜索是易失的新计算资源。但是我仍然很难看到POST和GET之间的界限。如果我想搜索图书馆中的所有科幻书籍,我将获得现有资源的集合,因此我很想使用GET,但是您建议将其视为POST,因为搜索本身就是一种新资源。因此,GET中的查询字符串应仅用于更改数据表示形式,而不用于过滤数据。我对吗?
cbliard

8
POST不应该用于搜索,应该使用GET,这样您可以共享和缓存结果URL和结果,并且可以更好地利用Internet的RESTful体系结构
Luxspes,2012年

37
这个答案听起来更像是尝试玩单词。按照这种逻辑,我们可以将所有内容都设为POST请求,并且仍然是RESTful。
supertonsky 2014年

9
这个答案似乎有些律师在跟我说话:-)问题实际上是“我确实有一个GET案例,好。但是我的查询字符串超出了允许的长度。我该如何处理”。拒绝这个答案。
G. Stoynev

2
如果遵循该逻辑,则每个请求都将创建一个资源并对其进行检索。
Alex

66

HTTP规范实际上建议在将数据发送到资源进行计算时使用POST

您的搜索看起来像是计算,而不是资源本身。如果您仍然希望将搜索结果作为资源,您可以做的是创建一个令牌以标识该特定搜索结果,并将用户代理重定向到该资源。

然后,您可以在一段时间后删除搜索结果标记。

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。


这如何满足有关将查询添加为书签的OP要求?
大黄

2
@Rhubarb确实通过为给定搜索创建资源来明确解决该问题。
maulik13

3
这将减慢结果。执行一个帖子,然后执行一个GET。它将至少增加300毫秒来获取搜索结果。
jaxxbo

链接已死
Emobe

我很困惑,服务器在POST和GET之间做什么?是否将搜索数据缓存在服务器上并仅等待GET请求进入?它必须使用一些唯一的ID来执行此操作,因此您可以检索缓存。您的回答很好,但肯定不完整。并且使用缓存将使事情变得无状态。
亚历山大·米尔斯

5

REST是一种做事的方式,而不是协议。即使您实际上不喜欢POST也不喜欢POST,它也可以工作。

如果您将/必须保留GET,POST等的“标准”定义,而不是考虑发布查询,则该查询将以查询ID存储在服务器上,以后再使用GET by ID进行查询。


4

关于您的示例:http://compute.com?content={base64file},我将使用POST,因为您正在上传要计算的“内容”。对我来说,这种“东西”感觉更像是一个简单参数的资源。

与此相反,在常规搜索中,我将开始坚持使用GET和参数。您可以使api客户端更轻松地测试和使用api。尽可能简化只读访问(在大多数情况下,这是大部分流量)!

但是大查询字符串的困境是GET的有效限制。只要您不达到此限制,我在这里就会实用,只要使用GET和url-params。这将在98%的搜索案例中起作用。仅在达到此限制后采取行动,然后在有效载荷中引入POST(具有mime类型Content-Type: application/x-www-form-urlencoded)的。

你有更多真实的例子吗?


该计算是真实示例。关于搜索,我们希望能够搜索多个卖点上的交易,因此我们打开一个新的浏览器窗口以选择卖点。并且当我们验证时​​,我们在搜索表单中修改了一个隐藏参数来设置选定的卖点。如果确实有很多,则结果搜索请求将具有非常长的查询字符串。
cbliard

4

围绕GET的困惑是浏览器的局限性。如果要为A2A或P2P应用程序创建RESTful接口,则GET的长度没有限制。

现在,如果您碰巧想要使用浏览器来查看RESTful接口(又名在开发/调试期间),那么您将遇到此限制,但是有一些工具可以解决此问题。


6
“ GET是浏览器限制”-也是服务器限制。您会发现所有Web服务器都实施了限制,如果您有CDN,它们也可能会实施限制。使用其他工具执行请求不会绕过服务器限制。
Courtney Miles

0

这是个简单的。使用POST。HTTP不会对GET的URL长度施加限制,但是服务器会这样做。务实,并通过POST解决。

您也可以使用GET主体(允许),但这是双重打击,因为它使用不正确,并且可能会出现服务器问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.