已存在匹配资源导致资源创建POST失败的HTTP响应代码

18

想象一下,我们有一个API,可以通过向其进行POST请求来创建一个新的员工,该请求应该发送到

www.example.com/api/employees

员工可以被描述为:

{
  name: "John Smith",
  tax_number: "ABC123"
}

税号在所有人中是唯一的。如果创建了一个记录,并且该记录中的名称和税号与现有记录匹配,那么可以安全地假设请求者希望返回对该记录的引用(包括其内部ID和客户端可能没有的其他数据,例如创建时间,更新时间)。

如果要返回该资源,HTTP状态码会是多少呢?我想使用重定向来返回ID,但我更喜欢在响应中封装整个对象。

这种情况是针对简单的重复错误而言的,因为如果尝试进行复制操作,则意味着您希望创建的记录已经存在,而不是与现有记录冲突。


可能是REST HTTP状态码用于验证失败或无效重复的重复问题。 - Joshua Taylor
但也请参见当资源已经存在时POST的HTTP响应代码 - Joshua Taylor
2个回答

21

我认为如果您向API发布资源,您希望收到状态码201,表示资源已创建,而且正文可能包含该资源。

否则,您首先必须检查资源是否已创建,但这将需要两个调用。

否则,您将得到状态码409:

由于与资源当前状态的冲突,无法完成请求。

[编辑]阅读amundsen,Ruby和Richardson关于Restfull Web APIs后

最好使用状态码409,表示服务器上存在冲突的资源。在响应的Location标头中放置“有冲突”的资源的URL,并在正文中添加冲突消息。


从HTTP/1.1规范中可以看出:“只有在预期用户可能解决冲突并重新提交请求的情况下,才允许使用此代码。” 我认为这并不适合这种情况。 - metacubed
但是在这里,他试图创建一个具有与后端已经创建的另一个资源相同的税号的资源。因此,消息可以返回已经创建的资源冲突,并在主体中返回该资源。但是这也可以使用403状态码 forbidden 来完成,具有相同的错误消息。 - Cedric Dumont
没错,但是对于一个 409 错误,消费者该如何解决冲突呢?他们很难去更改人的税号,不是吗? :D 实际上,除了向用户显示失败原因的错误信息外,什么也做不了。 - metacubed
409状态表示冲突,在返回的主体中,他可以拥有冲突的资源。但如果不接受409,则我会选择403禁止而不是500,因为对我来说,500状态代码表示代码问题、未处理的异常或其他内部缺陷。 - Cedric Dumont
我认为在这种情况下解决409错误,客户端应用程序需要显示一个消息,说明现有的税号已经存在,他们是否想要更新现有的资源。解决冲突并不意味着您需要再次尝试相同的方法,在这种情况下,如果用户想要编辑,则获取最新的税号副本,然后进行更改。 - nrjohnstone
@metacubed 完整的语句是:“响应正文应包含足够的信息,以便用户识别冲突的来源。理想情况下,响应实体应包含足够的信息,以便用户或用户代理程序修复问题;但这可能不可能,并且不是必需的。”(http://www.webdav.org/specs/rfc2616.html#status.409)因此,在这种情况下,409仍然有效。 - JWAspin

1

有一个409 Conflict响应代码,通常用于告知客户端该实体已存在于服务器上。虽然需要解析错误响应的主体可能不太直观,但如果在API文档中指定了此内容,则不应该有问题(将有关原始条目的信息放入响应主体中)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接