HTTP条件PUT

时间:2019-03-20 00:33:40

标签: http http-put idempotent

通过阅读answer上关于idempotency of HTTP PUT的问题,我了解到条件PUT请求的一个有趣方面,它导致了以下问题。

HTTP条件请求的规范在section 3.1中定义:

  

如果接收到原始服务器,则不得执行请求的方法    If-Match条件评估为false;而是原始服务器    必须使用以下任一方式响应:a)412(失败的前提条件)状态码    或b)2xx(成功)状态代码之一(如果原始服务器)    已经确认正在请求状态更改,并且最终    状态已经反映在目标的当前状态中    资源(即,用户代理请求的更改已经    成功,但是用户代理可能不知道它,也许    因为先前的响应丢失或进行了兼容的更改    由其他一些用户代理)。在后一种情况下,原始服务器    除非可以,否则不得在响应中发送验证者头字段    验证请求是否与之前的更改重复    由同一用户代理制作。

有条件的PUT请求用于避免多个代理在同一资源上并行操作(使用乐观锁定)时丢失更新的问题。 让我们假设资源的价值是

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "0"

{ "value": 0 }

现在,两个客户端希望同时增加该值,并发送一个包含新值的正文的PUT请求和一个If-Match标头。

PUT /value HTTP/1.1
Content-Type: application/json
If-Match: "0“

{ "value": 1 }

服务器在状态为200OK)的第一个请求上回答,而在状态为412Precondition Failed)的第二个请求上回答,即第二个客户端必须重复他的任务(获取,更新资源,并使用带有新etag值的If-Match标头将其放置)。

现在,我们假设两个客户端都没有收到答案,因此都再次发送了请求(显然,他们必须使用相同的If-Match标头)。根据规范,服务器必须返回相同的状态码,即200返回第一个,412返回第二个。如果服务器将两者都返回200,则更新将丢失,并且如果服务器将两者都返回412,则两个客户端都将重新开始,并且最后的值将为3。 / p>

我的问题是这如何在服务器端实现。我认为服务器必须存储所有状态更改的历史记录以及客户端的标识。但是如何识别客户?将client-ip和User-Agent标头组合起来就足够了吗?

是否有(Java)库来实现此行为? 我也不清楚哪个验证者标头字段一定不能发送给客户端。

0 个答案:

没有答案