947

我正在使用基于 REST 的 API 构建应用程序,并且已经到了为每个请求指定状态代码的地步。

对于未通过验证的请求或请求尝试在我的数据库中添加副本的位置,我应该发送什么状态代码?

我浏览了http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html但似乎都不对。

发送状态码时是否有常见的做法?

4

8 回答 8

894

对于输入验证失败:400 Bad Request + 您的可选描述。这是在“ RESTful Web Services ”一书中提出的。对于双重提交:409 冲突


2014 年 6 月更新

相关规范曾经是RFC2616,它使用 400 (Bad Request) 相当狭窄

由于语法错误,服务器无法理解该请求

因此,可能有人认为它不适合语义错误。但不再是了;自 2014 年 6 月起,取代之前的 RFC2616 的相关标准RFC 7231更广泛地使用了400(错误请求)作为

由于被认为是客户端错误,服务器无法或不会处理请求

于 2010-07-20T13:05:04.603 回答
285
  • 验证失败:403 Forbidden(“服务器理解请求,但拒绝执行”)。与流行的观点相反,RFC2616 并没有说“403 仅用于失败的身份验证”,而是“403:我知道你想要什么,但我不会那样做”。这种情况可能是也可能不是由于身份验证。
  • 尝试添加重复:409 Conflict(“由于与资源的当前状态冲突,请求无法完成。”)

您绝对应该在响应标头和/或正文中给出更详细的解释(例如,使用自定义标头 - X-Status-Reason: Validation failed)。

于 2010-07-20T13:24:04.537 回答
263

我推荐状态码 422, "Unprocessable Entity"

11.2. 422 无法处理的实体

422(Unprocessable Entity)状态码意味着服务器理解请求实体的内容类型(因此 415(Unsupported Media Type)状态码是不合适的),并且请求实体的语法是正确的(因此是 400(Bad Request) ) 状态码不合适)但无法处理包含的指令。例如,如果 XML 请求正文包含格式正确(即语法正确)但语义错误的 XML 指令,则可能会出现这种错误情况。

于 2010-07-20T14:56:26.783 回答
91

200,300、400、500 都是非常通用的。如果你想要通用,400 就可以了。

422 被越来越多的 API 使用,甚至被 Rails 开箱即用。

无论您为 API 选择哪种状态码,都会有人不同意。但我更喜欢 422,因为我认为“400 + 文本状态”太笼统了。此外,您没有利用 JSON-ready 解析器;相比之下,带有 JSON 响应的 422 非常明确,可以传达大量错误信息。

说到 JSON 响应,我倾向于对这种情况下的 Rails 错误响应进行标准化,即:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

这种格式非常适合表单验证,我认为就“错误报告的丰富性”而言,这是最复杂的情​​况。如果您的错误结构是这样的,它可能会处理您所有的错误报告需求。

于 2013-04-04T17:40:59.957 回答
76

数据库中的重复项应该是409 CONFLICT.

我建议使用422 UNPROCESSABLE ENTITY验证错误。

在这里对 4xx 代码进行了较长的解释。

于 2014-10-16T23:05:13.493 回答
63

200

呃......(309、400、403、409、415、422)......很多答案试图猜测、争论和标准化对于成功的 HTTP 请求失败的 REST 调用的最佳返回码是什么。

混合 HTTP 状态码和 REST 状态码是错误的。

但是,我看到许多实现混合了它们,许多开发人员可能不同意我的看法。

HTTP 返回码与HTTP Request自身有关。REST 调用是使用超文本传输​​协议请求完成的,它的工作级别低于调用的 REST 方法本身。REST 是一种概念/方法,其输出是业务/逻辑结果,而 HTTP 结果代码是传输结果。

例如,当您调用 /users/ 时返回“404 Not found”是令人困惑的,因为它可能意味着:

  • URI 错误 (HTTP)
  • 未找到用户 (REST)

“403 Forbidden/Access Denied”可能意味着:

  • 需要特别许可。浏览器可以通过询问用户/密码来处理它。(HTTP)
  • 服务器上配置了错误的访问权限。(HTTP)
  • 您需要经过身份验证(REST)

并且该列表可能会继续出现“500 服务器错误”(Apache/Nginx HTTP 抛出错误或 REST 中的业务约束错误)或其他 HTTP 错误等...

从代码中,很难理解失败的原因是什么,是 HTTP(传输)失败还是 REST(逻辑)失败。

如果 HTTP 请求在物理上成功执行,它应该总是返回 200 代码,无论是否找到记录。因为 URI 资源已找到并由 HTTP 服务器处理。是的,它可能会返回一个空集。是否可以接收一个带有 200 作为 HTTP 结果的空网页,对吗?

取而代之的是,您可能会返回带有一些选项的 200 HTTP 代码:

  • 如果出现问题,JSON 结果中的“错误”对象
  • 如果未找到记录,则为空 JSON 数组/对象
  • 布尔结果/成功标志与以前的选项相结合,以便更好地处理。

此外,一些互联网提供商可能会拦截您的请求并向您返回 404 HTTP 代码。这并不意味着找不到您的数据,而是在传输级别有问题。

来自维基

2004 年 7 月,英国电信供应商 BT Group 部署了 Cleanfeed 内容阻止系统,该系统会对 Internet Watch Foundation 确定为潜在非法内容的任何请求返回 404 错误。其他 ISP 在相同情况下返回 HTTP 403“禁止”错误。泰国和突尼斯也报道了使用虚假 404 错误作为隐藏审查的手段的做法。在 2011 年革命前审查制度严厉的突尼斯,人们开始意识到假 404 错误的本质,并创造了一个名为“Ammar 404”的虚构角色,代表“隐形审查员”。

为什么不简单地回答这样的问题?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

即使请求在逻辑上失败,谷歌总是在其地理编码 API 中返回 200 作为状态代码:https ://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

Facebook 总是为成功的 HTTP 请求返回 200,即使 REST 请求失败:https ://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

很简单,HTTP 状态码是针对 HTTP 请求的。REST API 是你的,定义你的状态码。

于 2017-09-23T12:42:37.640 回答
9

Ember-Data 的 ActiveRecord 适配器期望422 UNPROCESSABLE ENTITY从服务器返回。因此,如果您的客户端是用 Ember.js 编写的,您应该使用 422。只有这样 DS.Errors 才会填充返回的错误。您当然可以将 422 更改为适配器中的任何其他代码。

于 2014-12-03T22:17:18.443 回答
5

状态码 304 Not Modified也会对重复请求做出可接受的响应。这类似于处理If-None-Match使用实体标签的标头。

在我看来,@Piskvor 的答案是我认为原始问题的意图的更明显的选择,但我有一个也相关的替代方案。

如果您想将重复请求视为警告或通知而不是错误,则304未修改的响应状态代码和Content-Location标识现有资源的标头将同样有效。当意图仅仅是确保资源存在时,重复请求将不是错误而是确认。请求并没有错,只是简单的多余,客户端可以参考已有的资源。

换句话说,请求是好的,但是由于资源已经存在,服务器不需要进行任何进一步的处理。

于 2014-03-17T19:14:39.133 回答