带有URL查询参数的HTTP POST - 好主意与否?

时间:2009-03-04 18:42:52

标签: rest http

我正在设计一个API来覆盖HTTP,我想知道是否使用HTTP POST命令,但只使用URL查询参数而没有请求体,是一个很好的方法。

考虑:

  • “良好网页设计”要求通过POST发送非幂等操作。这是一种非幂等行为。
  • 当URL中存在请求参数时,更容易开发和调试此应用程序。
  • 该API不适合广泛使用。
  • 似乎在没有正文的情况下发出POST请求会花费更多的工作,例如必须明确添加Content-Length: 0标头。
  • 在我看来,没有正文的POST与大多数开发人员和HTTP框架的期望相悖。

通过URL查询而不是请求正文在POST请求上发送参数是否还有其他缺陷或优势?

编辑:正在考虑的原因是操作不是幂等的,并且除了检索之外还有副作用。见the HTTP spec

  

特别是,惯例已经   建立了GET和HEAD   方法不应该有   采取行动的重要性   而不是检索。这些方法应该   被认为是“安全的”。这允许用户   代理人代表其他方法,   例如POST,PUT和DELETE,在   特殊的方式,使用户成为   意识到可能的事实   正在要求采取不安全行动。

     

...

     

方法也可以具有的属性   “幂等”在那里(除了   错误或到期问题)   N的副作用> 0相同   请求与单个请求相同   请求。方法GET,HEAD,PUT   和DELETE共享此属性。也,   OPTIONS和TRACE应该是方法   没有副作用,等等   本质上是幂等的。

8 个答案:

答案 0 :(得分:224)

如果您的操作不是幂等的,那么必须使用POST。如果你不这样做,那你只是在寻找麻烦。 <{1}},GETPUT方法必需是幂等的。想象一下,如果客户端预先为您的服务预先提取DELETE个请求,那么您的应用程序会发生什么情况 - 如果这会导致客户端看到副作用,那么就会出现问题。

我同意发送带有查询字符串但没有正文的GET似乎很奇怪,但我认为在某些情况下它可能是合适的。

将URL的查询部分视为资源的命令,以限制当前请求的范围。通常,查询字符串用于对POST请求进行排序或过滤(例如GET),但我认为在?page=1&sort=title上也有意义限制范围(可能像POST })。

答案 1 :(得分:119)

每个人都是对的:坚持使用POST来处理非幂等请求。

如何同时使用URI查询字符串和请求内容?那么它是有效的HTTP(见注1),为什么不呢!

这也是完全合乎逻辑的:URL(包括其查询字符串部分)用于定位资源。而HTTP方法谓词(POST - 及其可选的请求内容)用于指定操作,或如何处理资源。那些应该是正交问题。 (但是,对于ContentType = application / x-www-form-urlencoded的特殊情况,它们并不是完美正交的问题,请参阅下面的注释2.)

注1:HTTP规范(1.1)没有规定查询参数和内容对接受POST或PUT请求的HTTP服务器是互斥的。所以任何服务器都可以自由接受。即如果你写服务器那么没有什么可以阻止你选择接受这两者(除了可能是一个不灵活的框架)。通常,服务器可以根据它想要的任何规则来解释查询字符串。它甚至可以用引用其他标题的条件逻辑来解释它们,例如Content-Type,这导致注2:

注意2:如果 Web浏览器是人们访问您的Web应用程序的主要方式, application / x-www-form-urlencoded 是Content-Type他们正在发布,然后您应该遵循该Content-Type的规则。 application / x-www-form-urlencoded的规则更加具体(坦率地说,不常见):在这种情况下,您必须将URI解释为一组参数,而不是资源位置。 [这与Powerlord提出的有用点相同;可能很难使用Web表单将内容POST到您的服务器。刚才解释得有点不同。]

注3:最初的查询字符串是什么? RFC 3986将HTTP查询字符串定义为URI部分,作为定位资源的非分层方式。

如果读者提出这个问题希望问什么是好的RESTful架构:RESTful架构模式不需要URI方案以特定的方式工作。 RESTful架构关注系统的其他属性,如资源的可缓存性,资源本身的设计(它们的行为,功能和表示),以及是否满足幂等性。或者换句话说,实现与HTTP协议及其HTTP方法动词集高度兼容的设计。 :-)(换句话说,RESTful架构对于资源的位置并不是很有用。)

最后注意事项:有时查询参数会用于其他事情,既不是资源定位也不是编码内容。曾经见过像'PUT = true'或'POST = true'这样的查询参数?这些是不允许您使用PUT和POST方法的浏览器的变通方法。虽然这些参数被视为URL查询字符串的一部分(在线上),但我认为它们不是URL的查询精神的一部分。

答案 2 :(得分:61)

你想要理由吗?这是一个:

Web表单不能用于向使用GET和POST混合的页面发送请求。如果将表单的方法设置为GET,则所有参数都在查询字符串中。如果将表单的方法设置为POST,则所有参数都在请求正文中。

来源:HTML 4.01标准,第17.13 Form Submission部分

答案 3 :(得分:7)

从程序化的角度来看,对于客户来说,它打包参数并将它们附加到网址上并进行POST与GET的对比。在服务器端,它正在从查询字符串而不是发布的字节中评估入站参数。基本上,它是一种清洗。

可能存在优点/缺点的可能是特定客户端平台如何在其网络堆栈中使用POST和GET例程,以及Web服务器如何处理这些请求。根据您的实现,一种方法可能比另一种方法更有效。知道这将指导你的决定。

尽管如此,从程序员的角度来看,我更喜欢允许在主体中使用所有参数的POST,或者在URL上使用所有参数的GET,并使用任何POST请求明确忽略url参数。它避免了混淆。

答案 4 :(得分:5)

我认为在保持内容有效负载限制在POST主体的同时,拥有标识URL上资源的查询参数仍然可能非常RESTful。这似乎将“我要发送什么?”的考虑因素分开。与“我是谁将其发送给谁?”。

答案 5 :(得分:2)

REST阵营有一些指导原则,我们可以用来标准化我们使用HTTP动词的方式。这在构建RESTful API时非常有用。

简而言之: GET应该是只读的,即对服务器状态没有影响。 POST用于在服务器上创建资源。 PUT用于更新或创建资源。 DELETE用于删除资源。

换句话说,如果您的API操作更改了服务器状态,REST建议我们使用POST / PUT / DELETE,但不要使用GET。

用户代理通常明白做多个POST是不好的,并会发出警告,因为POST的意图是改变服务器状态(例如,结账时支付货款),你可能不希望这样做两次!

比较你可以随意做的GET(幂等)。

答案 6 :(得分:0)

最好在POST端点上使用查询参数,只要它们引用已经存在的资源即可。

例如:

POST /user_settings?user_id=4
{
  "use_safe_mode": 1
}

上面的POST具有一个查询参数,该参数指向现有资源。 body参数定义了要创建的新资源。

(当然,这可能是个人偏爱而不是教条原则。)

答案 7 :(得分:-12)

我同意 - 如果您只是在URL中而不是在正文中传递数据,那么使用GET请求可能会更安全。有关整个POST + GET概念的一些其他观点,请参阅this similar question