REST - ETag when POST to collection of resources and If-Match header
REST - ETag when POST to collection of resources and If-Match header
每个用户都有 collection 个 gem。这些 gem 可以通过 REST API:
访问
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
)gems,但这对我的问题并不重要。实际上,它很重要。请继续阅读。)
从 high-level 的角度来看,他们执行以下操作:
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
),而不是关于 collection 的资源(例如 /gem
)。也就是说,在步骤 3b
中,我提供了 gem 的完整 collection 的 ETag,而实际上我提供了一个要添加的 gem。
当然,您的问题听起来非常适合 ETag 的使用。它是一个集合这一事实并不重要;重要的是它是一种资源,您可以从中始终如一地生成 ETag。
要考虑的一件事是,如果集合的表示有任何可以更改的内容,而这对您的 API 消费者来说并不重要。例如,假设您以某种随机或不一致的顺序输出集合,但集合在语义上定义为无序。在这种情况下,您可以根据集合中的项目集生成 weak ETag。
每个用户都有 collection 个 gem。这些 gem 可以通过 REST API:
访问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
)gems,但这对我的问题并不重要。实际上,它很重要。请继续阅读。)
从 high-level 的角度来看,他们执行以下操作:
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
),而不是关于 collection 的资源(例如 /gem
)。也就是说,在步骤 3b
中,我提供了 gem 的完整 collection 的 ETag,而实际上我提供了一个要添加的 gem。
当然,您的问题听起来非常适合 ETag 的使用。它是一个集合这一事实并不重要;重要的是它是一种资源,您可以从中始终如一地生成 ETag。
要考虑的一件事是,如果集合的表示有任何可以更改的内容,而这对您的 API 消费者来说并不重要。例如,假设您以某种随机或不一致的顺序输出集合,但集合在语义上定义为无序。在这种情况下,您可以根据集合中的项目集生成 weak ETag。