gpt4 book ai didi

RESTful幂等

转载 作者:行者123 更新时间:2023-12-03 10:09:31 25 4
gpt4 key购买 nike

我正在设计一个利用ROA(面向资源的体系结构)的RESTful Web服务。

我正在尝试找到一种有效的方法来保证在服务器指定资源 key 的情况下创建新资源的PUT请求的幂等性。

据我了解,传统方法是创建一种交易资源,例如/CREATE_PERSON。用于创建新人员资源的客户端-服务器交互将分为两个部分:

步骤1:获取用于创建新的PERSON资源的唯一交易ID :::

**Client request:**
POST /CREATE_PERSON

**Server response:**
200 OK
transaction-id:"as8yfasiob"

步骤2:使用交易ID::: 在保证唯一的请求中创建新人员资源
**Client request**
PUT /CREATE_PERSON/{transaction_id}
first_name="Big bubba"

**Server response**
201 Created // (If the request is a duplicate, it would send this
PersonKey="398u4nsdf" // same response without creating a new resource. It
// would perhaps send an error response if the was used
// on a transaction id non-duplicate request, but I have
// control over the client, so I can guarantee that this
// won't happen)

我看到的这种方法的问题在于,它需要向服务器发送两个请求,以便执行创建新的PERSON资源的单个操作。这造成了性能问题,增加了用户等待客户端完成其请求的机会。

我一直在尝试消除用于消除第一步的想法,例如为每个请求预先发送transaction-id,但是我的大多数想法还有其他问题,或者涉及牺牲应用程序的无状态性。

有没有办法做到这一点?

编辑::::::

我们最终采用的解决方案是让客户端获取UUID并将其与请求一起发送。 UUID是一个非常大的数字,占用16个字节(2 ^ 128)的空间。与具有编程思想的人可能会直观地想到的相反,随机生成UUID并假定它是唯一值是公认的做法。这是因为可能值的数量如此之大,以至于随机生成相同数量的两个值的几率很低,几乎是不可能的。

一个警告是我们让客户从服务器请求一个UUID( GET uuid/)。这是因为我们不能保证客户端运行的环境。如果出现问题,例如在客户端上植入随机数生成器,那么很可能会发生UUID冲突。

最佳答案

您在创建操作中使用了错误的HTTP动词。 RFC 2616指定POSTPUT的操作的语义。

第9.5段:

POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line



第9.6段

PUT method requests that the enclosed entity be stored under the supplied Request-URI.



该行为有一些细微的细节,例如 PUT可用于在指定的URL创建新资源(如果尚不存在)。但是, POST永远不要将新实体放在请求URL上,而 PUT应该总是将任何新实体放在请求URL上。与请求URL的这种关系将 POST定义为 CREATE,并且 PUT定义为 UPDATE

根据该语义,如果要使用 PUT创建一个新的人,则应在 /CREATE_PERSON/{transaction_id}中创建它。换句话说,您的第一个请求返回的交易ID应该是用于稍后获取该记录的人员 key 。 您不应向不会成为该记录最终位置的URL发出PUT请求。

不过,更好的是,您可以通过使用 POST/CREATE_PERSON作为原子操作来完成此操作。这使您可以通过一个请求来创建新的人记录,并在响应中获得新的ID(也应在HTTP Location header 中引用该ID)。

同时,REST指南规定动词不应成为资源URL的一部分。因此,创建新人员的URL应该与获取所有人员列表的位置相同- /PERSONS(我更喜欢复数形式:-)。

因此,您的REST API变为:
  • 获取所有人-GET /PERSONS
  • 获取单例-GET /PERSONS/{id}
  • 创建新人-POST /PERSONS,正文包含新记录
  • 的数据
  • 更新现有人员或创建具有知名ID-PUT /PERSONS/{id}的新人员,其正文包含更新记录的数据。
  • 删除现有人员-DELETE /PERSONS/{id}

  • 注意:出于两个原因,我个人更喜欢不使用PUT创建记录,除非我需要创建一个子记录,该子记录具有与来自不同数据集的现有记录相同的ID(也称为“穷人的外键”: -))。

    更新:您是对的, POST不是幂等的,并且遵循HTTP规范。 POST将始终返回新资源。在上面的示例中,新资源将是事务上下文。

    但是,我的观点是,您希望将 PUT用于创建新资源(人员记录),并且根据HTTP规范,新资源本身应位于URL处。特别是,您的方法遇到的问题是,与 PUT一起使用的URL是POST创建的事务性上下文的表示,而不是新资源本身的表示。换句话说,人员记录是更新交易记录的副作用,而不是它的直接结果(更新的交易记录)。

    当然,通过这种方法, PUT请求将是幂等的,因为一旦创建了个人记录并且交易已“完成”,则后续的 PUT请求将不执行任何操作。但是现在您遇到了另一个问题-要实际更新该个人记录,您将需要向另一个URL发出 PUT请求-该请求代表个人记录,而不是创建该个人记录的交易。因此,现在您有两个单独的URL,您的API客户端必须知道这两个URL,并针对它们发出请求以操纵同一资源。

    或者,您也可以完整复制事务记录中复制的最后一个资源状态,并让人员记录更新也通过事务URL进行更新。但是在这一点上,事务URL是针对个人记录的意图和目的的,这意味着它首先是由 POST请求创建的。

    关于RESTful幂等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2954783/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com