HTTP PUT中的幂等性是什么?我可以禁止覆盖资源吗? [英] What is idempotency in HTTP PUT? Can I disallow overwriting of a resource?

查看:672
本文介绍了HTTP PUT中的幂等性是什么?我可以禁止覆盖资源吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写REST API,我希望允许具有适当权限的已认证用户通过此API上传文件.我以为我会使用PUT端点来处理此问题.我想包含一个故障保护,如果资源已经存在并且用户没有通过查询指定应该覆盖资源(即PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1),则请求将被拒绝,并带有400 -family错误.

I'm writing a REST API and I wish to allow authenticated users with the proper permissions to upload files via this API. I thought I'd use a PUT endpoint to handle this. I want to include a failsafe where the request will be rejected with a 400-family error if the resource already exists and the user did not specify via a query that the resource should be overwritten (i.e. PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1).

PUT的HTTP/1.1 RFC文档建议允许这种情况:

如果修改了现有资源,则应发送200(确定)或204(无内容)响应代码以指示请求已成功完成.如果无法使用Request-URI创建或修改资源,则应给出反映问题性质的适当错误响应.

If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem.

但是我对幂等的概念挂了电话. 规范说:

But I'm hung up on the concept of idempotency. The spec says:

方法也可以具有幂等"的特性,因为(错误或过期问题除外)N> 0个相同请求的副作用与单个请求的副作用相同.方法GET,HEAD,PUT和DELETE共享此属性.另外,OPTIONS和TRACE方法不应有副作用,因此本质上是幂等的.

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.

但是,即使按顺序执行的所有方法都是幂等的,几个请求的序列也可能是非幂等的. (如果整个序列的单次执行始终产生的结果不会因重新执行该序列的全部或一部分而改变,则该序列是幂等的.)例如,如果序列的结果取决于a,则该序列是非幂等的.值,然后按相同顺序进行修改.

However, it is possible that a sequence of several requests is non- idempotent, even if all of the methods executed in that sequence are idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that is not changed by a reexecution of all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence.

从定义上讲,永不产生副作用的序列是幂等的(前提是在同一组资源上不执行任何并发操作).

A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).

我无法解决这个问题,因为它适用于我的情况.如果PUT https://my.server.com/myfile.txt第一次运行时返回201 Created,则仅由于文件已存在而在后续请求中不执行任何其他操作而出现403 Forbidden409 Conflict错误,是否违反了幂等性概念?是否必须在URI上附加查询以绕过故障保护违反等幂性?

I can't wrap my head around this as it applies to my scenario. If PUT https://my.server.com/myfile.txt returns a 201 Created the first time it's run, then a 403 Forbidden or 409 Conflict error without doing anything else on a subsequent request simply because the file already exists, does that violate the concept of idempotency? Does having to tack a query onto the URI to bypass the failsafe violate idempotency?

推荐答案

这是幂等性的常见思维错误.

This is a common thinking mistake with idempotency.

规则的重点不是多个相同的请求获得相同的响应.

The point of the rule is NOT that multiple identical requests get the same response.

规则的要点是,如果多次发送相同的请求,则服务器的状态与仅发送一次的状态相同.

The point of the rule is that if you send the same request multiple times, the state of the server is the same as if you only sent it once.

因此,如果两次发送相同的请求,则第二个将出错并被忽略,但是服务器上的状态仍然与仅发送第一个相同.

So if you send the same request twice, the second will error and get ignored, but the state on the server is still the same as if you only sent the first.

更新后的HTTP标准有一个有趣的注释:

The updated HTTP standard has an interesting note though:

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

An origin server MUST NOT perform the requested method if a received If-Match condition evaluates to false; instead, the origin server MUST respond with either a) the 412 (Precondition Failed) status code or b) one of the 2xx (Successful) status codes if the origin server has verified that a state change is being requested and the final state is already reflected in the current state of the target resource (i.e., the change requested by the user agent has already succeeded, but the user agent might not be aware of it, perhaps because the prior response was lost or a compatible change was made by some other user agent). In the latter case, the origin server MUST NOT send a validator header field in the response unless it can verify that the request is a duplicate of an immediately prior change made by the same user agent.

即使该段特定于使用If-Match标头,它也可能在此处适用.如果您可以检测到发送了完全相同的请求,则可能只想返回201 Created.不过,这与您的问题有点偏离主题.

Even though that paragraph is specific to using the If-Match header, it might apply here too. Maybe you want to just return 201 Created if you can detect that the exact same request was sent. That's kind of off-topic to your question though.

顺便说一句,您应该使用条件标题而不是?overwrite=1.如果您明确不想要允许客户端更新已创建的资源,则客户端可以简单地包括:

As an aside, you should use conditional headers instead of ?overwrite=1. If you explicitly don't want to allow a client to update a resource if it has been created, the client can simply include:

If-None-Match: *

然后,您的服务器可以返回412 Precondition Failed,向客户端发出信号,表明该资源是较早创建的.此外,如果要强制客户端始终包含此标头,则可以使用428 Precondition Required告诉客户端.

Then your server can return 412 Precondition Failed, signaling the client that the resource was created earlier. Furthermore, if you want to force a client to always include this header, you can use 428 Precondition Required to tell a client.

这篇关于HTTP PUT中的幂等性是什么?我可以禁止覆盖资源吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆