我正在使用基于 REST 的 API 构建应用程序,并且已经到了为每个请求指定状态代码的地步。
对于未通过验证的请求或请求尝试在我的数据库中添加副本的位置,我应该发送什么状态代码?
我已经查看了 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html,但似乎没有一个是正确的。
发送状态码时是否有常见的做法?
对于输入验证失败:400 Bad Request + 您的可选描述。这在“RESTful Web Services”一书中提出了建议。对于双重提交:409 Conflict
2014 年 6 月更新
相关规范曾经是 RFC2616,它使用 400(Bad Request)相当狭窄
由于语法错误,服务器无法理解该请求
因此,可能有人认为它不适合语义错误。但不再是了;自 2014 年 6 月起,取代之前的 RFC2616 的相关标准 RFC 7231 更广泛地将 400 (Bad Request) 用作
由于被认为是客户端错误,服务器无法或不会处理请求
验证失败:403 Forbidden(“服务器理解请求,但拒绝执行”)。与流行的观点相反,RFC2616 并没有说“403 仅用于失败的身份验证”,而是“403:我知道你想要什么,但我不会那样做”。这种情况可能是也可能不是由于身份验证。
尝试添加重复:409 Conflict(“由于与资源的当前状态冲突,请求无法完成。”)
您绝对应该在响应标头和/或正文中给出更详细的解释(例如,使用自定义标头 - X-Status-Reason: Validation failed
)。
HTTP/1.0 403 Form validation errors
是最干净的方法。
我推荐status code 422, "Unprocessable Entity"。
11.2. 422 Unprocessable Entity 422(Unprocessable Entity)状态码意味着服务器理解请求实体的内容类型(因此415(Unsupported Media Type)状态码是不合适的),并且请求实体的语法是正确的(因此400 (错误请求)状态代码不合适)但无法处理包含的指令。例如,如果 XML 请求正文包含格式正确(即语法正确)但语义错误的 XML 指令,则可能会出现这种错误情况。
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", ...]
}
}
这种格式非常适合表单验证,我认为就“错误报告的丰富性”而言,这是最复杂的情况。如果您的错误结构是这样的,它可能会处理您所有的错误报告需求。
arg1
有效,arg2
有效,但两者的组合以及发送的特定值是无效的。
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 代码。这并不意味着找不到您的数据,而是在传输级别有问题。
从 Wiki:
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."}
}
Google 始终在其地理编码 API 中返回 200 作为状态代码,即使请求在逻辑上失败:https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
对于成功的 HTTP 请求,Facebook 始终返回 200,即使 REST 请求失败:https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling
很简单,HTTP 状态码是针对 HTTP 请求的。 REST API 是你的,定义你的状态码。
BadRequest()
方法有自己的返回模型,它不同于您的常规返回模型。解析这是一场噩梦。 @KevinHooke,针对 REST 验证错误返回 HTTP 200 就像在说:“我收到了您的消息,答案是否定的,这就是原因。”返回 HTTP 400 说,“我不知道你在说什么。”
Ember-Data 的 ActiveRecord 适配器期望从服务器返回 422 UNPROCESSABLE ENTITY
。因此,如果您的客户端是用 Ember.js 编写的,您应该使用 422。只有这样 DS.Errors 才会填充返回的错误。 You can of course change 422 to any other code 在您的适配器中。
Status Code 304 Not Modified 也会对重复请求做出可接受的响应。这类似于使用实体标记处理 If-None-Match
的标头。
在我看来,@Piskvor 的答案是我认为原始问题的意图的更明显的选择,但我有一个也相关的替代方案。
如果您想将重复请求视为警告或通知而不是错误,则响应状态代码 304
Not Modified 和标识现有资源的 Content-Location
标头将同样有效。当意图仅仅是确保资源存在时,重复请求将不是错误而是确认。请求并没有错,只是简单的多余,客户端可以参考已有的资源。
换句话说,请求是好的,但是由于资源已经存在,服务器不需要进行任何进一步的处理。
something perceived to be a client error
,但本段中给出的所有示例都违反了 HTTP 协议,而不是逻辑错误:语法、帧、路由。因此,我认为 HTTP 规范不允许在应用程序级别上允许 400 验证失败。