REST - " change-all"的通用实践突变

时间:2014-10-26 09:21:33

标签: rest http

在我的应用程序中有一个按钮(单击时)应该对所有实体(某种类型)应用一些变异。假设我的实体是"购买"点击"确认全部"按钮应该导致服务器/数据库设置"确认"所有"购买的领域" to" true"。

我有在服务器端执行此操作的代码。我的问题是:我应该为此操作使用的URI是什么?

POST似乎是错误的选择,因为此操作幂等。因此,我留下了PUT。脑海中浮现出两个想法:

  • PUT /purchases?confirmed=true
  • PUT /purchaes/__all__?confirmed=true

有没有完善的惯例?

修改

还有第三种选择(Markus建议):

  • PUT /confirmations/?confirmed=true

当然,这可以起作用并且显然有其优点。我发现的(唯一)问题是确认不是我系统中的en实体。特别是没有GET /confirmations/some_id URI可能令人困惑。

1 个答案:

答案 0 :(得分:0)

首先,您应该用于此操作的URI是为该操作返回的购买集合的URI。 URI语义应该无关紧要。

其次,当我们说POST不是幂等的时,我们所说的是客户端不能默认假设该操作是幂等的。 POST方法的语义完全在你的控制之内,这就是为什么它们必须被记录下来,你不能依赖客户端事先知道它的作用,就像GET,PUT和DELETE一样。

简单来说,使用非幂等的PUT操作违反了HTTP方法语义,但是使用幂等的POST是可以的。

第三,你所做的是RPC,而不是REST。例如:

PUT /purchases?confirmed=true

您只是通过传递参数来调用方法。在REST中唯一有意义的方法是,如果您要创建或替换一组购买来替换confirmed=true的子集,这将与您想要的完全相反。如果你想做类似的事情,你应该使用POST,而不是PUT。

很明显,您的确认是部分更新,因此您根本不应该使用PUT。作为一般规则,如果您尝试为GET,PUT,PATCH和DELETE定义与特定资源耦合的单独语义,那么您做错了。这些方法应该是通用的,并且对于一切都以完全相同的方式工作。如果您需要将某些URI和方法耦合到特定的资源状态转换,请使用POST。

我不知道API的细节,但看起来你正在使用查询字符串参数作为有效负载参数。这也不是一个好主意,因为你不能将URI视为原子标识符。

如果你的URI是原子的,你可以说这会返回所有未经证实的购买:

GET /purchases?confirmed=false

您可以将POST记录为批量执行部分更新的方法,更改已过滤的子集:

POST /purchases?confirmed=false

{ "confirmed": true }

如果你坚持使用PUT,你应该做这样的事情。如果您的URI低于该值,则通过使用AND减少所有购买来返回全局确认状态:

GET /purchases/confirmation

{ "confirmed": False }

然后你可以做类似的事情:

PUT /purchases/confirmation

{ "confirmed": true }