【问题标题】:HTTP Status 412 (Precondition Failed) and Database VersioningHTTP 状态 412(前提条件失败)和数据库版本控制
【发布时间】:2010-09-01 16:31:38
【问题描述】:

我正在实现一个访问数据库的 RESTful Web 服务。对数据库中的实体进行版本控制以检测多个更新。例如,如果当前值为{"name":"Bill", "comment":"tinker", "version":3},如果一个用户PUTs{"name":"Bill", "comment":"tailor", "version":3},则请求成功(200 OK),新值为{"name":"Bill", "comment":"tailor", "version":4}。如果第二个用户 PUT {"name":"Bill", "comment":"sailor", "version":3"},该请求将失败(409 冲突),因为版本号不匹配。

现有的非RESTful接口,所以数据库的设计不能改变。 RESTful 接口调用现有的接口来处理检查版本的细节。

RESTful Web 服务的一个经验法则是尽可能遵循 HTTP 的细节。在这种情况下,如果版本不匹配,在请求中使用条件标头并返回 412 Precondition Failed 会更好吗?适当的标题似乎是 If-Match。此标头采用 ETag(实体标签),它可以是资源当前状态表示的哈希。

如果我这样做,ETag 将是为了外观,因为版本仍然是我正在测试的真实版本。

除了“让它更加 RESTful”之外,我还有什么理由应该这样做吗?

【问题讨论】:

    标签: http rest http-status-code-412


    【解决方案1】:

    如果您使用的是 HTTP,则应始终遵循 HTTP 规范,原因只是为了让了解规范的人正确运行

    412 仅应在前置条件(例如 If-Match)导致版本匹配失败时使用,而 409 应在实体会导致冲突时使用 (HTTP 规范本身在 definition of 409 中暗示了这种行为)。

    因此,不发送 ETag 的客户端不会期待 412。相反,发送 ETag 的客户端不会明白是 ETag 导致了 409。

    我会坚持一种方式。你说“数据库模式不能改变”,但这并不能阻止你(就在 HTTP 服务器层)从数据库表示中提取版本并将其放入 ETag,然后进入,获取 If-Match 标头并将其放回版本字段中。

    但是完全在实体本身中这样做是不被禁止的。它只需要您解释概念及其工作原理,而使用 ETag 解决方案,您只需将人们指向 HTTP 规范。

    编辑: 并且版本标志不必是当前资源的哈希值;一个版本是完全可以接受的。 ETag: "3" 是一个完全有效的 ETag。

    【讨论】:

    • 你对我的问题有任何线索吗:stackoverflow.com/questions/19009312/…
    • "版本标志不必是当前资源的哈希值" - 如果您想降低用户猜测预期版本的风险,则可以这样做并绕过并发检查。
    • Heh :-) 我并不是说 {{ETag: "3"}} 是个好主意...使其不透明通常是个好主意,尽管它会降低可见度。考虑 {{ETag: "3:eccbc8"}} — 其中 "eccbc8 是字符 "3" 的 md5sum 的前 6 个字符。这会强制客户端按预期方式使用实体标签;但保持可见性 ( “3”在那里,因此人们可以将其解释为“版本 3”)。我们仍然没有对实际内容进行哈希处理。
    猜你喜欢
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2018-05-29
    相关资源
    最近更新 更多