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

注意事项:

“好的网页设计”要求通过POST发送非幂等动作。这是非幂等的。 当请求参数出现在URL中时,更容易开发和调试这个应用程序。 该API并不打算广泛使用。 似乎要做一个没有正文的POST请求需要更多的工作,例如必须显式添加Content-Length: 0报头。 在我看来,没有正文的POST有点违背大多数开发人员和HTTP框架的期望。

在POST请求中通过URL查询而不是通过请求体发送参数还有什么缺点或优点吗?

编辑:考虑这一点的原因是操作不是幂等的,除了检索之外还有其他副作用。请参阅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.


当前回答

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

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

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

用户代理通常知道做多个POST是不好的,并会对此发出警告,因为POST的目的是改变服务器状态(例如。在收银台付款),你可能不想这样做第二次!

与GET相比,你可以经常这样做(幂等)。

其他回答

从编程的角度来看,对于客户端,它将参数打包并将它们附加到url上,并执行POST和GET操作。在服务器端,它计算来自查询字符串的入站参数,而不是发送的字节。基本上,这是一种洗涤。

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

尽管如此,从程序员的角度来看,我更倾向于允许在主体中包含所有参数的POST,或者在url上包含所有参数的GET,并且显式地忽略任何POST请求的url参数。这样可以避免混淆。

如果你的动作不是幂等的,那么你必须使用POST。如果你不这样做,你就是在自找麻烦。GET、PUT和DELETE方法必须是幂等的。想象一下,如果客户端预先获取您的服务的每个可能的GET请求,那么应用程序中会发生什么情况——如果这会导致客户端可见的副作用,那么一定是出了问题。

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

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

我认为使用查询参数来标识URL上的资源,同时将内容有效负载限制在POST主体中,仍然是非常RESTful的。这似乎把“我要发送什么?”和“我要发送给谁?”的考虑分开了。

每个人都是对的:对于非幂等的请求,坚持使用POST。

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

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

Note 1: HTTP specification (1.1) does not state that query parameters and content are mutually exclusive for a HTTP server that accepts POST or PUT requests. So any server is free to accept both. I.e. if you write the server there's nothing to stop you choosing to accept both (except maybe an inflexible framework). Generally, the server can interpret query strings according to whatever rules it wants. It can even interpret them with conditional logic that refers to other headers like Content-Type too, which leads to Note 2:

Note 2: if a web browser is the primary way people are accessing your web application, and application/x-www-form-urlencoded is the Content-Type they are posting, then you should follow the rules for that Content-Type. And the rules for application/x-www-form-urlencoded are much more specific (and frankly, unusual): in this case you must interpret the URI as a set of parameters, and not a resource location. [This is the same point of usefulness Powerlord raised; that it may be hard to use web forms to POST content to your server. Just explained a little differently.]

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

In case readers asking this question wish to ask what is good RESTful architecture: the RESTful architecture pattern doesn't require URI schemes to work a specific way. RESTful architecture concerns itself with other properties of the system, like cacheability of resources, the design of the resources themselves (their behavior, capabilities, and representations), and whether idempotence is satisfied. Or in other words, achieving a design which is highly compatible with HTTP protocol and its set of HTTP method verbs. :-) (In other words, RESTful architecture is not very presciptive with how the resources are located.)

最后注意:有时查询参数用于其他事情,既不是定位资源也不是编码内容。是否见过类似“PUT=true”或“POST=true”的查询参数?这些是不允许使用PUT和POST方法的浏览器的变通方法。虽然这些参数被视为URL查询字符串的一部分(在网络上),但我认为它们本质上不是URL查询的一部分。

你想要理由吗?这里有一个:

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

来源:HTML 4.01标准,17.13节表单提交