HTTP GET和POST的语义和限制

11
本周早些时候,我不得不做一些感觉上像是语义违规的事情。让我解释一下。
我正在制作一个简单的 AJAX 客户端应用程序,它将向一个给定参数的服务发出请求。由于整个应用程序基本上是只读的,所以我认为使用 HTTP GET 是正确的方式。其中一些必须传递的参数很简单(例如排序顺序或页码)。
然而,其中一个必需的参数可能有可变长度,这让我担心。由于我将所有参数都编码到 GET 请求的查询字符串中,因此对于请求 URL,这似乎放置了一个不必要的大约2000个字符的上限。而且无论如何,我也不喜欢看到500个字符长的请求URL。
因此,由于 POST 请求没有这样的限制,我决定切换。但这感觉不对。我有这样的印象:POST 表示数据的修改,但我正在将其用于一个简单的只读请求。
有没有更好的方法来执行带有许多参数的GET请求?我听说过一种方法-首先执行参数本身的预备POST,然后再执行GET。但是,这种技术还有很多不足之处。
但是,忽略这个特定案例,HTTP请求方法的真实语义和限制是什么?为什么GET不支持任何类型的参数有效负载?在URL中使用查询字符串几乎感觉像是一个hack。

为什么你认为“post”表示数据修改? - Conrad Frix
2
@ConradFrix:由于其用于提交表单、上传文件以及一般非幂等操作,因此如此。 - voithos
如果你正在编写一个Ajax应用程序,为什么要关心URL的长度?另外请注意,2000个字符的限制仅适用于浏览器URL,而不适用于Ajax请求(如您提供的链接中所述的评论部分)。 - Jonathan W
@JonathanW:我刚刚尝试了一些 AJAX 测试请求,似乎并非如此。使用 1000 个字符时,我会收到 404 Not Found(因为我使用的是虚假 URL)。使用 2000 个字符时,我会收到 400 Bad Request,因此它失败了。使用 100000 个字符时,我根本没有得到响应。 - voithos
1个回答

16

关于这个问题有几点需要注意:

  • HTTP规范(RFC 2616)并没有禁止GET请求携带参数,因此这不是HTTP GET语义本身的问题。然而,许多HTTP堆栈(用于客户端、服务或代理)禁止HTTP请求中包含正文,你不能使用它们主要是由于实现细节(相当普遍)而不是与HTTP GET请求语义问题相关。
  • 同样,URI(或查询字符串)长度的限制在RFC中也没有指定。这主要是由许多HTTP服务器堆栈实施的安全缓解措施,以防止恶意客户端消耗服务器资源(例如,在IIS / ASP.NET中,默认限制为2k,但可以通过web.config中的一些元素来增加它)。同样,这不是一个语义问题,而是一个实际问题。
  • 如果按照REST哲学,POST请求确实表示数据修改,但是有许多HTTP POST请求的只读操作的示例。SOAP在其所有请求中都使用POST,无论调用的操作是“安全”还是“修改”的。因此,您也可以将POST用于这些操作。但是,通过偏离REST(和“规范”的HTTP)用法,您将失去协议的某些功能,如可以应用于GET请求,但不适用于POST的缓存。
  • 您使用两个请求(带参数的POST + GET“获得”结果)的示例似乎过于复杂。正如我所提到的,POST请求不一定意味着修改资源,因此当一个请求足够时,您不必创建新的“协议”(POST+GET)来访问您的操作。

3
+1很好的回答,另一个重要观点是:GET应该是幂等的,因此客户端可以(并且会)自动重试,而POST则永远不会被重试。 - Francis Upton IV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接