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


当前回答

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

根据RFC 4918

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

其他回答

我觉得你不应该这么做。

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

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

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

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

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

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

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

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

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

在您的情况下,您可以使用409冲突

如果你想检查另一个HTTPs状态码从下面的列表

1××信息

100 Continue
101 Switching Protocols
102 Processing

2××成功

200 OK
201 Created
202 Accepted
203 Non-authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status
208 Already Reported
226 IM Used

3××重定向

300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
308 Permanent Redirect

4××客户端错误

400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Payload Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
418 I’m a teapot
421 Misdirected Request
422 Unprocessable Entity
423 Locked
424 Failed Dependency
426 Upgrade Required
428 Precondition Required
429 Too Many Requests
431 Request Header Fields Too Large
444 Connection Closed Without Response
451 Unavailable For Legal Reasons
499 Client Closed Request

5××服务器错误

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates
507 Insufficient Storage
508 Loop Detected
510 Not Extended
511 Network Authentication Required
599 Network Connect Timeout Error

在阅读了这篇文章和其他几篇关于状态码使用的长达数年的讨论之后,我得出的主要结论是,必须仔细阅读规范,重点关注正在使用的术语、它们的定义、关系和周围的上下文。

相反,从不同的答案中可以看出,经常发生的情况是,部分规范被剥离了上下文,并基于感觉和假设进行孤立的解释。

这将是一个相当长的回答,简短的总结是,HTTP 409是报告“添加新资源”操作失败的最合适的状态代码,如果具有相同标识符的资源已经存在。以下是对原因的解释,完全基于权威来源- RFC 7231中所述。

那么,在OP的问题中描述的情况下,为什么409冲突是最合适的状态代码?

RFC 7231对409冲突状态码的描述如下:

409(冲突)状态代码表示由于与目标资源的当前状态冲突而无法完成请求。

这里的关键组件是目标资源及其状态。

目标资源

RFC 7231对该资源的定义如下:

HTTP请求的目标称为“资源”。HTTP不限制资源的性质;它仅仅定义了一个可能用于与资源交互的接口。每个资源由统一资源标识符(Uniform resource Identifier, URI)标识,如[RFC7230]章节2.7所述。

因此,当使用HTTP接口时,我们总是通过对uri应用HTTP方法来操作由uri标识的资源。

当我们打算添加一个新资源时,基于OP的例子,我们可以:

在资源/objects/{id}中使用PUT; 对资源/对象使用POST。

/objects/{id}无关紧要,因为在使用PUT方法时不可能有冲突:

PUT方法请求用请求消息有效负载中包含的表示所定义的状态创建或替换目标资源的状态。

如果具有相同标识符的资源已经存在,它将被PUT替换。

我们将关注/objects资源和POST。

RFC 7231对POST说:

POST方法要求目标资源根据资源自己的特定语义处理请求中包含的表示。例如,POST用于以下函数(以及其他函数):…3)创建一个尚未被源服务器识别的新资源;4)将数据追加到资源的现有表示中。

与OP对POST方法的理解相反:

由于POST的意思是“追加”操作…

将数据追加到资源的现有表示只是可能的POST“函数”之一。此外,OP在提供的例子中实际上所做的不是直接将数据追加到/objects表示中,而是创建一个新的独立资源/objects/{id},然后它成为/objects表示的一部分。但这并不重要。

重要的是资源表示的概念,它把我们带到了……

资源状态

RFC 7231解释说:

考虑到资源可以是任何东西,并且HTTP提供的统一接口类似于一个窗口,通过该窗口,人们只能通过将消息传递给另一端的某个独立参与者来观察并对该事物采取行动,因此需要一个抽象来表示(“代替”)我们通信中该事物的当前或期望状态。这种抽象称为表示[REST]。

对于HTTP的目的,“表示”是旨在反映给定资源的过去、当前或期望状态的信息,其格式可以通过协议轻松通信,并由一组表示元数据和潜在的无限表示数据流组成。

这还不是全部,规范继续描述表示部分——元数据和数据,但是我们可以总结出,由元数据(报头)和数据(有效负载)组成的资源表示反映了资源的状态。

现在,我们了解了409冲突状态代码的用法所需的两个部分。

409年冲突

让我们重申:

409(冲突)状态代码表示由于与目标资源的当前状态冲突而无法完成请求。

那么它是如何合适的呢?

We POST to /objects => our target resource is /objects. OP does not describe the /objects resource, but the example looks like a common scenario where /objects is a resource collection, containing all individual "object" resources. That is, the state of the /objects resource includes the knowledge about all existing /object/{id} resources. When the /objects resource processes a POST request it has to a) create a new /object/{id} resource from the data passed in the request payload; b) modify its own state by adding the data about the newly created resource. When a resource to be created has a duplicate identifier, that is a resource with the same /object/{id} URI already exists, the /objects resource will fail to process the POST request, because its state already includes the duplicate /object/{id} URI in it.

这正是409冲突状态代码描述中提到的与目标资源当前状态的冲突。