POST 时数据不正确时的 HTTP 状态(使用不存在的资源 ID)

Posted

技术标签:

【中文标题】POST 时数据不正确时的 HTTP 状态(使用不存在的资源 ID)【英文标题】:HTTP status while POST with incorrect data (using id of resource which does not exist) 【发布时间】:2018-11-11 14:00:15 【问题描述】:

当我执行 POST 请求以创建新用户时,要返回的正确 HTTP 状态是什么,但其中一个参数不正确 - 我在用户数据中包含的公司 ID数据库中不存在。

发布 数据:用户名:'newuser',年龄:99,company_id:34

数据库中不存在 id 为 34 的公司。

我在想是否可以:

400,一种无效数据,但有效但不存在id 404 - 但不清楚哪个资源不存在 409,因为这是一种冲突,用户可以通过更改公司 ID 来解决此问题 422? 或 500 - 因为这是一种数据库错误,而不允许存在不存在的 id

【问题讨论】:

【参考方案1】:

400422

首先,请记住它是client error,所以5xx 状态码不适合这里。然后你应该选择一个4xx 状态码。

最明显的选项是400422

如果 JSON 语法无效,则返回 400。 如果 JSON 语法有效但其内容无效,则返回422,表示服务器无法处理请求实体。

请参阅RFC 4918 中的以下引用(对于您的情况,当它说 XML 时,请阅读 JSON):

11.2. 422 Unprocessable Entity

422(不可处理实体)状态码表示服务器 理解请求实体的内容类型(因此 415(不支持的媒体类型)状态码不合适),并且 请求实体的语法是正确的(因此是 400 (Bad Request) 状态码不合适)但无法处理包含的 指示。例如,如果 XML 请求正文包含格式正确(即语法正确),但是 语义错误的 XML 指令。

answer 解决了类似的情况。


例如,如果负载的内容包含无效值(但在语法上有效),GitHub API v3 也会返回 422

在 API 调用中存在三种可能的客户端错误类型 接收请求正文:

    发送无效的 JSON 将导致 400 Bad Request 响应。 [...]

    发送错误类型的 JSON 值将导致 400 Bad Request response。 [...]

    发送无效字段将导致422 Unprocessable Entity 响应。 [...]


Michael Kropat 将set of diagrams 放在一起,在选择最合适的状态代码时非常有见地。 4xx 状态码见下图:

【讨论】:

连接到WebDAV的这个状态怎么样?我在某处看到只有在支持 WebDAV 功能时才应该使用它。 @AgataAndrzejewska 某处在哪里? WebDAV 是一个 HTTP 扩展,422 是一个有效的 HTTP 状态码 registered in IANA。 我通常建议人们避免使用与 WebDAV 相关的状态代码,除非他们积极使用 WebDAV 标准作为其 API 的基础;我认为消费者会从一个晦涩的标准中挑选一个特定的(尽管是适当的)状态代码而忽略有关该标准的所有其他内容,这会让消费者感到困惑。 en.wikipedia.org/wiki/Principle_of_least_astonishment CassioMazzochiMolin,我在这篇文章中读过:keycdn.com/support/422-unprocessable-entity @PaulTurner 我在考虑简单性和清晰度以及 400 的描述“公司 ID 无效/不正确”。该请求似乎没有无效的语法问题。一般来说,我描述的 POST 请求似乎并不罕见,我没有看到 API 中返回很多 422 错误。【参考方案2】:

404 Not Found 是返回 POST 请求的有问题的状态。这意味着您发送请求的资源不存在;调用者的 URL 错误。

最明显(和通用)的答案是:400 Bad Request

这只是表明您的请求有问题(错误在于调用者而不是服务器),然后在您的响应正文中表达出问题的具体细节。这通常是处理请求验证的方式。


理想的答案是通过向他们所属的公司发送请求来添加用户:

POST /company/34
Content-Type: application/json

    "username": "newuser",
    "age": 99

这意味着调用者必须找到一个有效的company 资源才能将请求发送到。如果company/34 不存在,则404 Not Found 响应是合适的;您尝试将用户添加到不存在的公司。

这确实意味着您的 API 必须使用资源语义进行结构化,并且用户必须完全属于一家公司。

【讨论】:

我会选择422,如我的answer 中所述。【参考方案3】:

这里,这张图很不错,我用过很多次了。

Which code should I return?

我会选择 404。资源可能存在(不是格式错误)但它不存在(因此无法找到)。

【讨论】:

谢谢,根据这张图我应该用422。 404 在这里没有意义。 @CassioMazzochiMolin 您是否介意尝试添加一些有用的东西而不是无意义地抨击,比如为什么我的推理是错误的?

以上是关于POST 时数据不正确时的 HTTP 状态(使用不存在的资源 ID)的主要内容,如果未能解决你的问题,请参考以下文章

Redux - 异步 - 输入字段更改时的 POST 状态

在 C++ 中使用 Wininet 发送 POST 请求时的编码问题

处理 http post 时使用哪些 http 状态代码?

Spring MVC HTTP 状态 405 - 不支持请求方法“POST”

HTTP协议

HTTP 状态 405 - 此 URL 不支持 HTTP 方法 POST