我正在构建一个允许客户端存储对象的服务器。这些对象是在客户端完全构造的,对象id在对象的整个生命周期内都是永久的。

我已经定义了API,以便客户端可以使用PUT创建或修改对象:

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

{id}是对象id,所以它是Request-URI的一部分。

现在,我也在考虑允许客户端使用POST创建对象:

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

由于POST意味着“追加”操作,我不确定在对象已经存在的情况下该做什么。我应该把请求作为修改请求,还是应该返回一些错误代码(哪个)?


当前回答

“302 Found”对我来说听起来合乎逻辑。RFC 2616说除了GET和HEAD之外,它还可以被其他请求回答(当然也包括POST)

但是它仍然让访问者通过RFC访问这个URL来获得这个“已找到”的资源。为了使它直接指向真正的“Found”URL,应该使用“303 See Other”,这是有意义的,但强制另一个调用GET它后面的URL。好的方面是,这个GET是可缓存的。

我想我会用“303 See Other”。我不知道我是否可以响应在主体中发现的“东西”,但我想这样做,以节省到服务器的一次往返。

更新:在重新阅读RFC后,我仍然认为不存在的“4XX+303 Found”代码应该是正确的。然而,“409冲突”是现有的最好的答案代码(正如@ wrkken指出的那样),可能包括指向现有资源的Location头。

其他回答

也许是在游戏后期,但我在尝试创建REST API时偶然发现了这个语义问题。

为了稍微扩展一下wrkken的回答,我认为您可以根据情况使用409 Conflict或403 Forbidden -简而言之,当用户完全无法解决冲突并完成请求时使用403错误(例如,他们不能发送DELETE请求来显式删除资源),或者如果可能做一些事情,则使用409。

10.4.4禁止403 服务器理解请求,但拒绝执行。 授权没有帮助,请求不应该重复。如果 请求方法不是HEAD,服务器希望公开 为什么要求没有被满足,它应该描述原因 对于实体中的拒绝。如果服务器不希望做出 此信息可用于客户端,状态代码404(不是 Found)可以代替。

现在,有人说“403”,就会想到权限或身份验证问题,但规范说,这基本上是服务器告诉客户端它不会这样做,不要再问了,这就是客户端不应该这样做的原因。

至于PUT vs. POST…当用户没有办法或不应该为资源创建标识符时,POST应该用于创建资源的新实例。当资源的标识已知时,使用PUT。

9.6 PUT ... The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.

我的感觉是409冲突是最合适的,但是,在野外当然很少见到:

The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required. Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.

208- http://httpstatusdogs.com/208-already-reported怎么样?这是一个选择吗?

在我看来,如果唯一的东西是重复资源,就不应该引发错误。毕竟,客户端和服务器端都没有错误。

我觉得你不应该这么做。

如您所知,POST用于修改集合,并用于CREATE一个新项。所以,如果你发送id(我认为这不是一个好主意),你应该修改集合,即,修改项目,但这是令人困惑的。

使用它添加一个项目,没有id。这是最好的做法。

如果您想捕获一个UNIQUE约束(而不是id),您可以响应409,就像在PUT请求中一样。但不是身份证。

就我个人而言,我倾向于WebDAV扩展422不可处理实体。

根据RFC 4918

422不可处理实体状态码意味着服务器理解请求实体的内容类型(因此415不支持的媒体类型状态码是不合适的),并且请求实体的语法是正确的(因此400坏请求状态码是不合适的),但无法处理包含的指令。