我正在实现一个访问数据库的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 Conflict),因为版本号不匹配.
存在非RESTful接口,因此无法更改数据库的设计.RESTful接口调用现有接口来处理检查版本的详细信息.
RESTful Web服务中的经验法则是尽可能遵循HTTP的详细信息.在这种情况下,在请求中使用条件头并且如果版本不匹配则返回412 Precondition Failed会更好吗?相应的标题似乎是If-Match.该头部采用ETag(实体标签),其可以是资源的当前状态的表示的散列.
如果我这样做,ETags将出于外表的缘故,因为版本仍然是我正在测试的真实的东西.
有什么理由我应该这样做,除了"让它更加RESTful",无论这意味着什么?
如果你正在使用HTTP,那么适当的做法是始终遵循HTTP规范,原因只是让了解规范的人能够正常运行.
412只应在前提条件(例如If-Match)导致版本匹配失败时才使用,而如果实体会导致冲突,则应使用409(HTTP规范本身在409的定义中暗示了这种行为).
因此,不发送ETag的客户端将不会期望412.相反,发送ETag的客户端将不会理解它是导致409的ETag.
我会坚持一种方式.你说"数据库模式不能改变",但这并不能阻止你(在HTTP服务器层中)从数据库表示中提取版本并将其放入ETag中,然后在途中,获取If-Match标头并将其放回版本字段中.
但是不禁止在实体主体中完全做到这一点.它只需要您解释概念及其工作原理,而使用ETag解决方案,您可以将人们指向HTTP规范.
编辑:版本标志不必是当前资源的哈希值; 一个版本是完全可以接受的 ETag: "3"
是一个完全有效的ETag.