正在使用具有可接受的副作用(REST)的PUT


9

每当用户更新表单时,我都想创建一个撤消历史记录。因为这是更新,所以我想使用PUT请求。但是,我读到PUT不需要有副作用

在这里使用PUT是否可以接受?有更好的选择吗?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

在服务器中

doPut('person/:personId',
   // create a new person snapshot
)

编辑:

用户可以看到该历史记录,多次调用将产生多个版本。

解决方案是在创建版本之前检查该版本是否唯一。

Answers:


11

起草HTTP / 2的人在保留旧含义的同时,对HTTP应该做什么的想法更加冗长。让我们看看HTTP / 2草案规范对幂等的看法:

4.2.2。幂等方法

如果使用该方法的多个相同请求在服务器上的预期效果与单个请求的效果相同,则该请求方法被视为“幂等”。在本规范定义的请求方法中,PUT,DELETE和安全请求方法是幂等的。

就像保险柜的定义一样,幂等属性仅适用于用户所要求的内容;服务器可以自由地单独记录每个请求,保留修订控制历史记录或为每个幂等请求实现其他非幂等副作用

每个这样的PUT请求对服务器预期效果更新该URI标识的资源。这正是您的情况。

您决定对资源进行版本控制实际上并不重要。如果您不想在没有任何更改的情况下创建新版本,则需要将PUT请求中的有效负载与资源的最新版本(或以其他方式标识)进行比较,并且在所有属性均未更改的情况下您可以选择不创建新版本


您的编辑:

历史记录对用户可见,多次调用将导致多次转换

就资源而言,这没有副作用。该URI处的资源不会更改(相同的属性将获得PUT)。历史只是元数据,因为它很可能是由不同的URI或具有不同的请求标头请求的。


除外,因为您回答了我的特定问题:“ PUT创建用户可见的历史记录是否可以接受”,并给我一个解决方案,谢谢
roo2 2013年

这是什么问题的解决方案?该time属性是否已更新?我认为这也是元数据,即使它资源也是如此。
CodeCaster

1
问题在于,如果发送了多个PUT,则用户将获得冗长的撤消历史记录以及冗余信息。检查唯一性可以解决
roo2 2013年

12

HTTP区分两个属性:

  • 幂等
  • 安全

幂等性由规范定义如下:

方法还可以具有“ 幂等 ” 的属性,因为(除错误或过期问题外)N> 0个相同请求的副作用与单个请求的副作用相同。的方法GETHEADPUTDELETE这种属性。而且,这些方法OPTIONS和方法TRACE 不应有副作用,因此本质上是幂等的。

和安全:

特别是,已经建立了约定:GETHEAD方法不应具有除检索之外的其他任何操作。这些方法应该被认为是“ 安全的 ”。这允许用户代理代表其他的方法,比如POSTPUTDELETE,以特殊的方式,让用户知道的是正在请求操作可能是不安全的事实。

自然地,不可能确保服务器不会由于执行GET请求而产生副作用;实际上,一些动态资源认为该功能。这里的重要区别是用户没有要求副作用,因此不能对它们负责。

请注意,安全性意味着幂等:如果一种方法没有副作用,那么多次执行将产生与一次执行相同的副作用,即没有副作用。

这将方法分为三类:

  • 安全(因而也幂等): ,GET,,HEADOPTIONTRACE
  • 幂等,但并不一定安全:PUTDELETE
  • 既不是幂等也不安全的: POST

PUT不需要有副作用。

那是错的。PUT是幂等但不安全的。这样做的全部目的PUT是产生副作用,即更新资源。幂等性意味着多次更新具有相同内容的相同资源应具有与仅更新一次具有相同的效果。

请注意有关安全性(强调我的部分)的最后一段:

自然地,不可能确保服务器不会由于执行GET请求而产生副作用;实际上,一些动态资源认为该功能。这里的重要区别是用户没有要求副作用,因此不能对它们负责

尽管这句话讲的是GET安全性,但我们可以假设作者也打算对PUT等幂和幂等使用相同的推理。IOW:PUT应该只有一个用户可见的副作用,即更新命名资源。它可能还有其他副作用,但用户不承担任何责任。

例如,PUT幂等的事实意味着我可以根据需要多次重试:规范保证多次执行与一次执行完全相同。创建旧修订的待办事项作为这些多个PUT请求的副作用是完全有效的。但是,如果由于多次重试而导致您的数据库充满了旧版本的待办事项列表,那不是我的问题,那是您的问题。

爱荷华州:允许您有任意多的副作用,但是

  1. 它必须看起来像用户的请求是幂等的
  2. 您应对这些副作用负责,而不是用户

是的,幂等性与正在放置的资源的状态有关,而不与受PUT行为影响的任何其他服务器/服务状态有关。
Marjan Venema 2013年

赞成就休息中的安全性和幂等性作很好的解释
roo2

很好的解释。但是,您可以这样声明:“ PUT的全部目的是产生副作用,即更新资源。” 除非您用“副作用”一词表示的意思不同于“除了主要的预期作用之外发生的次要或无意的事情”,否则这似乎是一个矛盾。
MarredCheese

@MarredCheese:我在标准编程含义中使用该术语,它的基本意思是“不是返回值的任何“结果””。
约尔格W¯¯米塔格

嗯当然了 感谢您的澄清。
MarredCheese

1

您是正确的,PUT不需要有任何副作用,但是我会为此添加一些内容。

PUT不需要对正在执行该PUT操作的资源产生任何负面影响

您正在更新person标识为的资源F02E395A235,因此使用PUT是正确的。现在作为业务规则,您还可以跟踪对调用实体(REST服务的使用者)不可见的更改。这不会在person资源中添加新项目。无法使用/person/端点访问历史快照。因此,我认为,在这种情况下,PUT应该是完全可以接受的。


1
不会对所放置的资源产生任何副作用,但是完全可以接受对其他内容(计数器,日志记录,审计跟踪等)的任何副作用。
Marjan Venema 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.