我正在构建一个允许客户端存储对象的服务器。这些对象是在客户端完全构造的,对象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意味着“追加”操作,我不确定在对象已经存在的情况下该做什么。我应该把请求作为修改请求,还是应该返回一些错误代码(哪个)?


当前回答

更有可能是400个坏请求

[* * 6.5.1。400错误请求**][1]

400(坏请求)状态代码表示服务器不能或 将不会处理请求由于某些东西被认为是 客户端错误(例如,格式错误的请求语法,无效的请求 消息框架,或欺骗性请求路由)。

由于请求包含重复的值(已经存在的值),因此可以将其视为客户机错误。需要在下次尝试之前更改请求。 通过考虑这些事实,我们可以得出HTTP STATUS 400错误请求的结论。

其他回答

在检查重复记录的正确代码时偶然发现了这个问题。

请原谅我的无知,但我不明白为什么每个人都忽略了代码“300”,它清楚地表示“多项选择”或“模棱两可”

在我看来,这将是构建非标准或特定系统供自己使用的完美代码。我也可能是错的!

https://www.rfc-editor.org/rfc/rfc7231#section-6.4.1

“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头。

我会选择422不可处理实体,当请求无效时使用,但问题不在于语法或身份验证。

作为反对其他答案的论据,使用任何非4xx错误代码将暗示它不是客户端错误,而它显然是。使用非4xx错误代码来表示客户端错误完全没有意义。

It seems that 409 Conflict is the most common answer here, but, according to the spec, that implies that the resource already exists and the new data you are applying to it is incompatible with its current state. If you are sending a POST request, with, for example, a username that is already taken, it's not actually conflicting with the target resource, as the target resource (the resource you're trying to create) has not yet been posted. It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history." The request to create another user with that username is just unprocessable, having nothing to do with any version conflict.

为了记录,422也是GitHub使用的状态码,当您尝试按已使用的名称创建存储库时。

我觉得你不应该这么做。

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

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

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

这完全取决于上下文,以及谁负责处理重复的请求(服务器或客户端或两者都有)


如果服务器只是指向副本,请查看4xx:

400坏请求——服务器不会处理一个请求,因为这是明显的客户端错误 409冲突——如果服务器不处理请求,但原因不是客户端的错 ...

对于副本的隐式处理,请参阅2XX:

200好了 201年创建 ...

如果服务器希望返回一些东西,请查看3XX:

302年发现的 303查看其他 ...

当服务器能够指向现有资源时,就意味着重定向。


如果以上还不够,那么在响应体中准备一些错误消息总是一个很好的做法。