关于休息:带有URL查询参数的HTTP POST – 好主意与否?

HTTP POST with URL query parameters — good idea or not?

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

注意事项:

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

通过URL查询而不是请求主体在POST请求上发送参数是否还有任何缺陷或优势?

编辑:正在考虑的原因是操作不是幂等的,并且除了检索之外还有副作用。请参阅HTTP规范:

In particular, the convention has been
established that the GET and HEAD
methods SHOULD NOT have the
significance of taking an action other
than retrieval. These methods ought to
be considered"safe". This allows user
agents to represent other methods,
such as POST, PUT and DELETE, in a
special way, so that the user is made
aware of the fact that a possibly
unsafe action is being requested.

...

Methods can also have the property of
"idempotence" in that (aside from
error or expiration issues) the
side-effects of N > 0 identical
requests is the same as for a single
request. The methods GET, HEAD, PUT
and DELETE share this property. Also,
the methods OPTIONS and TRACE SHOULD
NOT have side effects, and so are
inherently idempotent.


如果你的行为不是幂等的,那么你必须使用POST。如果你不这样做,那你只是在寻找麻烦。 GETPUTDELETE方法必须是幂等的。想象一下,如果客户端预先获取了对您的服务的每个可能的GET请求,您的应用程序会发生什么 - 如果这会导致客户端看到副作用,那么就会出错。

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

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


每个人都是对的:坚持使用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查询的一部分。


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

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

资料来源:HTML 4.01标准,第17.13节表格提交


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

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

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


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


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

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

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

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

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


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