【问题标题】:How to handle PUT endpoint with immutable resource如何使用不可变资源处理 PUT 端点
【发布时间】:2021-05-20 19:06:02
【问题描述】:

我开发的微服务公开了一个端点 PUT /deployments/{uuid} 。端点用于启动可能代价高昂的部署操作,因此我们只希望它发生一次,这就是我们选择 PUT + UUID 而不是 POST 的原因(为了唯一性)。部署是不可变的,因此它永远无法更新,因此如果 PUT 被多次调用且使用相同的 uuid,我们目前会引发异常。

作为一个喜欢骑自行车并因此深深地关心休息的人,这让我感到厌烦。 PUT 应该是幂等的,因此在多次发出相同请求后引发异常是一种反模式。但是,我们有一个要求,不允许连续的相同请求生成新的部署,所以通常的 POST 不可用。

虽然最好的解决方案是可行的,但如果可能的话,我希望我们的解决方案更优雅一点。我已经在有效载荷中使用 UUID 放置了一个 POST,但我的团队似乎认为这比当前的解决方案更糟糕。我正在考虑只将 200 OK 从 PUT 返回到相同的 UUID 而不是 201 CREATED,但我不确定这是否与 non-idempotent-put 存在相同的问题,即没有在语义上传达我想要的信息。

这里有“最佳解决方案”吗?或者,如果我进一步追求这一点,我是否注定要成为团队中的“那个人”(开你的玩笑,我已经是那个人了)。

tl;dr 什么是不可变的 /deployments 端点的正确 RESTful API 签名,并且要求不允许同一请求被处理两次?

【问题讨论】:

    标签: rest http server


    【解决方案1】:

    幂等并不意味着“2 个相同的请求应该产生相同的响应”。意思是:“2次相同请求后的服务器状态应该与只发出1次时相同”。

    类似的例子,如果你在一个资源上调用DELETE 并得到一个204 No Content,然后再次调用DELETE 并得到一个404,这并不违反幂等性要求。第二次删除后,资源仍然被删除,就像第一次删除一样。

    所以允许多个相同的幂等请求给出不同的响应。

    尽管如此,我认为第二个相同的请求也返回 2xx 状态可能会更好。它不必与第一个相同。

    用例是客户端发送 HTTP 请求但在收到响应之前断开连接。客户端应该重试,如果服务器检测到请求与第一次相同,服务器可以只给客户端一个成功响应(但不要做任何事情)。

    这通常是个好主意,因为如果客户端收到第二个请求的错误,则可能更难知道请求失败是因为它较早成功还是其他原因。

    话虽如此,这里还有一种方法可以让你吃蛋糕。

    客户端可以将以下标头与PUT 请求一起发送:

    If-None-Match: *
    

    如果客户端省略了头部,你总是可以返回424 Precondition Required

    如果资源尚不存在,则为成功响应。如果资源是之前创建的,可以返回412 Precondition Failed

    使用这种机制,客户端有一个标准的方法来确定请求失败是因为之前发出了成功的请求。

    【讨论】:

    • 哦,哇,幂等性的区别是一个不为人知的重要区别,感谢您的澄清。
    【解决方案2】:

    基于文档herePUT 是最好的使用方法。当它触发部署时响应应该是201,当没有任何改变时响应应该是200204。它不应该是POST,因为调用POST 端点两次应该都会触发效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2017-01-27
      相关资源
      最近更新 更多