11

我正在实现一个访问数据库的 RESTful Web 服务。对数据库中的实体进行版本控制以检测多个更新。例如,如果当前值为{"name":"Bill", "comment":"tinker", "version":3},如果一个用户 PUT {"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”之外,我有什么理由这样做吗?

4

1 回答 1

20

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

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

因此,不发送 ETags 的客户端不会期待 412。相反,发送 ETags 的客户端不会理解导致 409 的 ETags。

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

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

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

于 2010-09-02T15:19:23.627 回答