我正在编写REST API,我希望允许具有适当权限的已认证用户通过此API上传文件。我以为我会使用PUT
端点来处理此问题。我想包含一个故障保险,其中如果资源已经存在并且用户未通过查询指定应覆盖资源(即400
),则请求将被拒绝,并返回PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1
系列错误
The HTTP/1.1 RFC documentation of PUT建议允许这种情况:
如果修改了现有资源,则应发送200(确定)或204(无内容)响应代码以指示请求已成功完成。如果无法使用Request-URI创建或修改资源,则应给出反映问题性质的适当错误响应。
但是我对幂等的概念挂了电话。 The spec says:
方法也可以具有“幂等”的特性,因为(错误或过期问题除外)N> 0个相同请求的副作用与单个请求的副作用相同。 GET,HEAD,PUT和DELETE方法共享此属性。另外,OPTIONS和TRACE方法不应有副作用,因此本质上是幂等的。
但是,即使按顺序执行的所有方法都是幂等的,几个请求的序列也可能是非幂等的。 (如果整个序列的单次执行始终产生的结果不会因重新执行该序列的全部或一部分而改变,则该序列是幂等的。)例如,如果序列的结果取决于a,则该序列是非幂等的。值,然后按相同顺序进行修改。
从定义上讲,永不产生副作用的序列是幂等的(前提是在同一组资源上不执行任何并发操作)。
我无法解决这个问题,因为它适用于我的情况。如果PUT https://my.server.com/myfile.txt
第一次运行时返回201 Created
,则仅由于文件已存在而在后续请求上不执行任何其他操作而发生403 Forbidden
或409 Conflict
错误,就这样做了违反了幂等的概念?是否必须在URI上附加查询以绕过故障保护违反幂等性?
答案 0 :(得分:1)
这是一个幂等的常见思维错误。
该规则的重点不是多个相同的请求获得相同的响应。
规则的要点是,如果多次发送相同的请求,则服务器的状态与仅发送一次的状态相同。
因此,如果您发送相同的请求两次,则第二个将出错并被忽略,但是服务器上的状态仍然与仅发送第一个相同。
更新后的HTTP标准虽然有一个interesting note:
如果接收到原始服务器,则不得执行请求的方法 If-Match条件评估为false;而是原始服务器 必须使用以下任一方式响应:a)412(失败的前提条件)状态码 或b)2xx(成功)状态代码之一(如果原始服务器) 已经确认正在请求状态更改,并且最终 状态已经反映在目标的当前状态中 资源(即,用户代理请求的更改已经 成功,但是用户代理可能不知道它,也许 因为先前的响应丢失或进行了兼容的更改 由其他一些用户代理)。在后一种情况下,原始服务器 除非可以,否则不得在响应中发送验证者头字段 验证请求是否与之前的更改重复 由同一用户代理制作。
即使该段特定于使用If-Match
标头,它也可能在此处适用。如果您可以检测到发送了完全相同的请求,则可能只想返回201 Created
。不过,这与您的问题有点偏离主题。
顺便说一句,您应该使用条件标题代替?overwrite=1
。如果您明确不想要允许客户端更新已创建的资源,则客户端可以简单地包括:
If-None-Match: *
然后,您的服务器可以返回412 Precondition Failed
,向客户端发出信号,指出该资源是先前创建的。此外,如果要强制客户端始终包含此标头,则可以使用428 Precondition Required
来告诉客户端。
答案 1 :(得分:0)
在以下API标准适用的情况下,当我引用“协议标准”时经常使用它们。
所有功劳归于:https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md 以下是Microsoft REST服务应支持的方法的列表。并非所有资源都支持所有方法,但是使用以下方法的所有资源都必须符合其用法。