避免与REST重复发布

避免与REST重复发布,rest,post,atomicity,Rest,Post,Atomicity,我一直在RESTAPI中使用POST来创建对象。每隔一段时间,服务器将创建对象,但客户端将在收到201 Created响应之前断开连接。客户端只看到一个失败的POST请求,稍后再试,服务器很高兴地创建了一个重复的对象 其他人一定有这个问题,对吧?但我到处搜索,每个人似乎都忽视了这一点 我有两种解决方案: A) 改为使用PUT,并在客户端上创建(GU)ID B) 向客户端上创建的所有对象添加GUID,并让服务器强制执行其唯一性 A与现有框架不太匹配,B感觉像是黑客。在现实世界中,其他人是如何解决这

我一直在RESTAPI中使用POST来创建对象。每隔一段时间,服务器将创建对象,但客户端将在收到
201 Created
响应之前断开连接。客户端只看到一个失败的POST请求,稍后再试,服务器很高兴地创建了一个重复的对象

其他人一定有这个问题,对吧?但我到处搜索,每个人似乎都忽视了这一点

我有两种解决方案:

A) 改为使用PUT,并在客户端上创建(GU)ID

B) 向客户端上创建的所有对象添加GUID,并让服务器强制执行其
唯一性

A与现有框架不太匹配,B感觉像是黑客。在现实世界中,其他人是如何解决这个问题的

编辑:


使用Backbone.js,您可以在客户端上创建对象时将GUID设置为id。当它被保存时,主干将执行PUT请求。将REST后端句柄设置为不存在的id,就可以设置了。

我总是使用B——由于服务器端的任何问题而检测DUP。

您可以尝试两步方法。您请求创建一个对象,该对象返回一个令牌。然后在第二个请求中,使用令牌请求状态。在使用令牌请求状态之前,您将使其处于“暂存”状态

如果客户机在第一个请求后断开连接,那么他们将不会拥有令牌,并且对象将无限期地处于“暂存”状态,或者直到您使用另一个进程将其删除

如果第一个请求成功,您就拥有一个有效的令牌,您可以任意多次抓取创建的对象,而无需重新创建任何内容

没有理由认为令牌不能作为数据存储中对象的ID。您可以在第一次请求期间创建对象。第二个请求实际上只是更新“staged”字段。

服务器发出的标识符 如果您要处理的是服务器发出标识符的情况,请在临时的暂存状态下创建对象。(这是一个固有的非幂等操作,因此应该使用POST来完成。)然后,客户端必须对其执行进一步的操作,以将其从暂存状态转移到活动/保留状态(这可能是资源属性的PUT,或对资源的适当POST)

每个客户机都应该能够以某种方式获得其处于暂存状态的资源列表(可能与其他资源混合),并且如果它们仍然处于暂存状态,则应该能够删除它们创建的资源。您还可以定期删除已停用一段时间的暂存资源

您不需要向任何其他客户端透露一个客户端的暂存资源;它们只需要在确认步骤之后才能在全球范围内存在

客户端发出的标识符 另一种选择是由客户机发出标识符。这在建模文件存储之类的东西时非常有用,因为文件名通常对用户代码很重要。在这种情况下,您可以使用PUT来创建资源,就像您可以以幂等方式创建资源一样


缺点是客户端可以创建ID,因此您无法控制它们使用什么ID。

针对这一点提出的另一个解决方案是,服务器生成一次性POST URI,当多次使用时,将导致服务器返回405响应

缺点是1)POE草案被允许在标准化方面没有任何进一步进展的情况下过期,因此2)实现它需要更改客户端以使用新的POE头,并且服务器需要额外的工作来实现POE语义

通过谷歌搜索,你可以找到一些正在使用它的API

我解决这个问题的另一个想法是写一篇有条件的文章,我描述了这篇文章并征求了反馈意见


在无法在客户端上生成唯一URI并因此需要POST的情况下,对于防止创建重复资源的最佳方法似乎没有达成一致意见。

重复的检测是一个难题,可能会变得非常复杂。真正不同但相似的请求可以同时到达,可能是因为网络连接已恢复。如果网络连接中断,重复请求可能会间隔数小时或数天到达

所有关于其他ANWSER中标识符的讨论都是为了在响应重复请求时给出一个错误,但这通常只会促使客户端获取或生成一个新id,然后重试

解决此问题的一个简单而健壮的模式如下:服务器应用程序应该存储对不安全请求的所有响应,然后,如果它们看到重复的请求,它们可以重复前面的响应,而不做其他任何事。对所有不安全请求执行此操作,您将解决一系列棘手的问题。“重复”由应用程序级别id确定,可以是客户端生成的GUID,也可以是服务器生成的序列号。在第二种情况下,请求-响应应该专门用于交换id。我喜欢这种解决方案,因为专门的步骤会让客户认为他们得到了他们需要照顾的宝贵东西。如果他们能够生成自己的标识符,他们就更有可能将这一行放在循环中,每个血腥的请求都会有一个新的id

使用此方案,所有POST都为空,POST仅用于检索操作标识符。所有的PUT和DELETE都是完全幂等的:连续的请求得到相同的(存储和重放)响应,并且不会导致进一步的事情发生。这个图案最棒的地方是它的功夫(熊猫)品质。它有一个弱点:客户在收到意外响应时,往往会重复一个请求,并将其转化为一种强制力:-)


如果有人关心的话,我有一个小小的谷歌文档。

这个问题还有另一个变体。