我正在使用基于rest的API构建一个应用程序,并且已经到了为每个请求指定状态代码的地步。
我应该发送什么状态代码的请求失败验证或请求试图添加一个副本在我的数据库?
我已经在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上找过了,但是没有一个是对的。
发送状态码时有什么惯例吗?
我正在使用基于rest的API构建一个应用程序,并且已经到了为每个请求指定状态代码的地步。
我应该发送什么状态代码的请求失败验证或请求试图添加一个副本在我的数据库?
我已经在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上找过了,但是没有一个是对的。
发送状态码时有什么惯例吗?
当前回答
数据库中的副本应该是409冲突。
我建议使用422 UNPROCESSABLE ENTITY来处理验证错误。
我在这里对4xx代码做了更详细的解释。
其他回答
200,300,400,500都是很通用的。如果你想要普通的,400就可以了。
422被越来越多的api使用,甚至被开箱即用的Rails使用。
无论您为API选择哪种状态代码,总会有人不同意。但我更喜欢422,因为我认为“400 +文本状态”太一般了。此外,您没有利用json就绪的解析器;相比之下,带有JSON响应的422非常显式,可以传递大量错误信息。
说到JSON响应,我倾向于在这种情况下对Rails错误响应进行标准化,即:
{
"errors" :
{
"arg1" : ["error msg 1", "error msg 2", ...]
"arg2" : ["error msg 1", "error msg 2", ...]
}
}
这种格式非常适合表单验证,我认为就“错误报告丰富度”而言,表单验证是最复杂的情况。如果您的错误结构是这样的,那么它可能会处理您所有的错误报告需求。
对于输入验证失败:400坏请求+您的可选描述。这在“rest式Web服务”一书中得到了建议。 对于双重提交:409冲突
2014年6月更新
相关的规范曾经是RFC2616,它给出了400(坏请求)的使用范围相当狭窄
由于语法错误,服务器无法理解请求
因此,可能有人认为它不适用于语义错误。但现在不是了;自2014年6月起,相关标准RFC 7231取代了之前的RFC2616,更广泛地使用400(坏请求)
服务器不能或 将不会处理请求由于某些东西被认为是 客户端错误
200
啊…(309、400、403、409、415、422)……大量的答案试图猜测,争论和标准化什么是一个成功的HTTP请求和一个失败的REST调用的最佳返回代码。
将HTTP状态代码和REST状态代码混合使用是错误的。
然而,我看到许多实现混合了它们,许多开发人员可能不同意我的观点。
HTTP返回码与HTTP请求本身相关。REST调用是使用超文本传输协议(Hypertext Transfer Protocol)请求完成的,它的工作级别比调用的REST方法本身要低。REST是一种概念/方法,其输出是业务/逻辑结果,而HTTP结果代码是传输结果。
例如,当你调用/users/时返回“404 Not found”是令人困惑的,因为它可能意味着:
URI错误(HTTP) 没有找到用户(REST)
“403禁止/拒绝访问”可能是指:
需要特别许可。浏览器可以通过询问用户/密码来处理它。(HTTP) 服务器上配置的访问权限错误。(HTTP) 您需要进行身份验证(REST)
这个列表可能会继续出现“500服务器错误”(Apache/Nginx HTTP抛出错误或REST中的业务约束错误)或其他HTTP错误等……
从代码中,很难理解失败的原因是什么,HTTP(传输)失败还是REST(逻辑)失败。
如果HTTP请求物理上被成功执行,它应该总是返回200个代码,不管是否找到记录。因为URI资源是由HTTP服务器找到并处理的。是的,它可能返回一个空集。有可能收到一个空网页200作为HTTP结果,对吗?
相反,你可以返回200个HTTP代码和一些选项:
如果出现错误,JSON结果中的"error"对象 如果没有发现记录,则为空JSON数组/对象 一个bool result/success标志,结合前面的选项以获得更好的处理。
此外,一些互联网提供商可能会拦截您的请求并返回404 HTTP代码。这并不意味着您的数据找不到,而是在传输级别上出了问题。
从维基:
In July 2004, the UK telecom provider BT Group deployed the Cleanfeed content blocking system, which returns a 404 error to any request for content identified as potentially illegal by the Internet Watch Foundation. Other ISPs return a HTTP 403 "forbidden" error in the same circumstances. The practice of employing fake 404 errors as a means to conceal censorship has also been reported in Thailand and Tunisia. In Tunisia, where censorship was severe before the 2011 revolution, people became aware of the nature of the fake 404 errors and created an imaginary character named "Ammar 404" who represents "the invisible censor".
为什么不简单地这样回答呢?
{
"result": false,
"error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}
谷歌总是在他们的地理编码API中返回200作为状态代码,即使在逻辑上请求失败:https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
Facebook总是返回200成功的HTTP请求,即使REST请求失败:https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling
很简单,HTTP状态码是用于HTTP请求的。REST API是你的,定义你的状态代码。
数据库中的副本应该是409冲突。
我建议使用422 UNPROCESSABLE ENTITY来处理验证错误。
我在这里对4xx代码做了更详细的解释。
状态代码304 Not Modified也会对重复的请求做出可接受的响应。这类似于使用实体标记处理If-None-Match的报头。
在我看来,@Piskvor的答案是更明显的选择,我认为是原始问题的意图,但我有一个替代方案,也是相关的。
如果希望将重复请求视为警告或通知,而不是错误,响应状态码304 Not Modified和标识现有资源的Content-Location头同样有效。当意图仅仅是确保资源存在时,重复的请求将不是错误,而是确认。请求并不是错误的,只是多余的,客户端可以引用现有的资源。
换句话说,请求是好的,但是由于资源已经存在,服务器不需要执行任何进一步的处理。