REST - 在POST到资源集合时的ETag和If-Match标题

时间:2016-08-09 06:31:09

标签: java rest concurrency etag

每个用户都有一组宝石。可以通过REST API访问这些gem:

GET    /user/<user id>/gem              -> get all gems
GET    /user/<user id>/gem/<gem id>     -> get an existing gem
POST   /user/<user id>/gem              -> add a new gem
PUT    /user/<user id>/gem/<gem id>     -> edit an existing gem
DELETE /user/<user id>/gem/<gem id>     -> delete an existing gem

我有几个后端进程,它们可以并发运行,并且可以通过POST HTTP方法添加gems。 (他们也可以编辑(PUT)或删除(DELETE)宝石,但这对我的问题并不重要。实际上,它是。请继续阅读。)

从高级别的角度来看,他们会做以下事情:

1.  GET /user/<current user id>/gem
2.  some calculations, based on step 1
3a. if (step 2 decided that a gem should be added)
3b.     POST /user/<current user id>/gem

如上所述,这些过程并行运行。通常,两个进程不管理同一用户的gem,但可能会发生。

因此,如果在此期间发生变化,我需要一种机制来禁止步骤POST中的3b。我想过使用ETags和乐观锁定:

1.  GET /user/<current user id>/gem and remember the returned ETag
2.  some calculations, based on step 1
3a. if (step 2 decided that a gem should be added)
3b.     POST /user/<current user id>/gem with header 'If-Match=<ETag from step 1>'
3c.     if (server returns 412 - precondition failed)
3d.         start again at step 1

我不确定ETag是否适用于此。 ETag的大多数示例都是关于一个资源(例如/gem/23),而不是关于资源集合(例如/gem)。也就是说,在步骤3b中,我提供了完整宝石集合的ETag,而实质上我提供了一个单独的宝石。

1 个答案:

答案 0 :(得分:0)

当然,您的问题听起来非常适合使用ETag。它是一个集合的事实并不重要;重要的是,它是一种具有表示的资源,您可以始终从中生成ETag。

要考虑的一件事是,是否有关于集合的表示的任何内容可以改变,这对您的API消费者来说并不重要。例如,假设您以一些随机或不一致的顺序输出集合,但集合在语义上被定义为无序。在这种情况下,您可以根据集合中的项目集生成weak ETag