我正在使用基于 REST 的 API 构建应用程序,并且已经到了为每个请求指定状态代码的地步。
对于未通过验证的请求或请求尝试在我的数据库中添加副本的位置,我应该发送什么状态代码?
我浏览了http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html但似乎都不对。
发送状态码时是否有常见的做法?
我正在使用基于 REST 的 API 构建应用程序,并且已经到了为每个请求指定状态代码的地步。
对于未通过验证的请求或请求尝试在我的数据库中添加副本的位置,我应该发送什么状态代码?
我浏览了http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html但似乎都不对。
发送状态码时是否有常见的做法?
对于输入验证失败:400 Bad Request + 您的可选描述。这是在“ RESTful Web Services ”一书中提出的。对于双重提交:409 冲突
2014 年 6 月更新
相关规范曾经是RFC2616,它使用 400 (Bad Request) 相当狭窄
由于语法错误,服务器无法理解该请求
因此,可能有人认为它不适合语义错误。但不再是了;自 2014 年 6 月起,取代之前的 RFC2616 的相关标准RFC 7231更广泛地使用了400(错误请求)作为
由于被认为是客户端错误,服务器无法或不会处理请求
您绝对应该在响应标头和/或正文中给出更详细的解释(例如,使用自定义标头 - X-Status-Reason: Validation failed
)。
我推荐状态码 422, "Unprocessable Entity"。
11.2. 422 无法处理的实体
422(Unprocessable Entity)状态码意味着服务器理解请求实体的内容类型(因此 415(Unsupported Media Type)状态码是不合适的),并且请求实体的语法是正确的(因此是 400(Bad Request) ) 状态码不合适)但无法处理包含的指令。例如,如果 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", ...]
}
}
这种格式非常适合表单验证,我认为就“错误报告的丰富性”而言,这是最复杂的情况。如果您的错误结构是这样的,它可能会处理您所有的错误报告需求。
200
呃......(309、400、403、409、415、422)......很多答案试图猜测、争论和标准化对于成功的 HTTP 请求但失败的 REST 调用的最佳返回码是什么。
混合 HTTP 状态码和 REST 状态码是错误的。
但是,我看到许多实现混合了它们,许多开发人员可能不同意我的看法。
HTTP 返回码与HTTP Request
自身有关。REST 调用是使用超文本传输协议请求完成的,它的工作级别低于调用的 REST 方法本身。REST 是一种概念/方法,其输出是业务/逻辑结果,而 HTTP 结果代码是传输结果。
例如,当您调用 /users/ 时返回“404 Not found”是令人困惑的,因为它可能意味着:
“403 Forbidden/Access Denied”可能意味着:
并且该列表可能会继续出现“500 服务器错误”(Apache/Nginx HTTP 抛出错误或 REST 中的业务约束错误)或其他 HTTP 错误等...
从代码中,很难理解失败的原因是什么,是 HTTP(传输)失败还是 REST(逻辑)失败。
如果 HTTP 请求在物理上成功执行,它应该总是返回 200 代码,无论是否找到记录。因为 URI 资源已找到并由 HTTP 服务器处理。是的,它可能会返回一个空集。是否可以接收一个带有 200 作为 HTTP 结果的空网页,对吗?
取而代之的是,您可能会返回带有一些选项的 200 HTTP 代码:
此外,一些互联网提供商可能会拦截您的请求并向您返回 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 是你的,定义你的状态码。
Ember-Data 的 ActiveRecord 适配器期望422 UNPROCESSABLE ENTITY
从服务器返回。因此,如果您的客户端是用 Ember.js 编写的,您应该使用 422。只有这样 DS.Errors 才会填充返回的错误。您当然可以将 422 更改为适配器中的任何其他代码。
状态码 304 Not Modified也会对重复请求做出可接受的响应。这类似于处理If-None-Match
使用实体标签的标头。
在我看来,@Piskvor 的答案是我认为原始问题的意图的更明显的选择,但我有一个也相关的替代方案。
如果您想将重复请求视为警告或通知而不是错误,则304
未修改的响应状态代码和Content-Location
标识现有资源的标头将同样有效。当意图仅仅是确保资源存在时,重复请求将不是错误而是确认。请求并没有错,只是简单的多余,客户端可以参考已有的资源。
换句话说,请求是好的,但是由于资源已经存在,服务器不需要进行任何进一步的处理。