我正在使用基于REST的API构建一个应用程序,并且已经达到了为每个请求指定状态代码的程度.
对于未通过验证的请求或请求尝试在我的数据库中添加副本的情况,我应该发送什么状态代码?
我查看了http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html,但似乎没有一个是正确的.
发送状态代码时是否有通用做法?
对于输入验证失败:400 Bad Request +您的可选说明.这在" RESTful Web Services " 一书中有所建议.对于双提交:409冲突
2014年6月更新
相关规范曾经是RFC2616,它使用了400(差错请求)
由于语法格式错误,服务器无法理解请求
因此可能有人认为它不适合语义错误.但不是更多; 自2014年6月起,相关标准RFC 7231(取代之前的RFC2616 )更广泛地使用400(错误请求)
由于被认为是客户端错误的东西,服务器不能或不会处理请求
验证失败:403 Forbidden("服务器理解请求,但拒绝履行请求").与流行的观点相反,RFC2616没有说"403仅用于失败的身份验证",但"403:我知道你想要什么,但我不会这样做".该条件可能是也可能不是由于身份验证.
尝试添加副本:409 Conflict("由于与资源的当前状态冲突,无法完成请求.")
您应该在响应标头和/或正文中提供更详细的说明(例如,使用自定义标头 - X-Status-Reason: Validation failed
).
我建议使用状态码422,"Unprocessable Entity".
11.2.422不可处理的实体
422(不可处理实体)状态代码表示服务器理解请求实体的内容类型(因此415(不支持的媒体类型)状态代码是不合适的),并且请求实体的语法是正确的(因此400(错误请求) )状态代码不合适)但无法处理包含的指令.例如,如果XML请求主体包含格式正确(即语法正确)但语义错误的XML指令,则可能发生此错误情况.
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", ...] } }
这种格式非常适合表单验证,我认为这是"错误报告丰富度"方面最复杂的案例.如果您的错误结构是这样,它可能会处理您的所有错误报告需求.
数据库中的副本应该是a 409 CONFLICT
.
我建议使用422 UNPROCESSABLE ENTITY
验证错误.
我在这里给出了4xx代码的更长解释:http://parker0phil.com/2014/10/16/REST_http_4xx_status_codes_syntax_and_sematics/
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数组/对象
bool结果/成功标志与之前的选项相结合,以便更好地处理.
此外,一些互联网服务提供商可能会拦截您的请求并返回404 HTTP代码.这并不意味着您的数据未找到,但在传输级别出现问题.
来自维基:
2004年7月,英国电信提供商BT集团部署了Cleanfeed内容阻止系统,该系统对因互联网观察基金会认定为可能违法的内容的任何请求返回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
即使REST请求失败,Facebook总是返回200以获得成功的HTTP请求: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未修改也会对重复请求做出可接受的响应.这类似于处理If-None-Match
使用实体标签的标头.
在我看来,@ Piskvor的答案是我认为原始问题的意图更明显的选择,但我有一个也是相关的替代方案.
如果要将重复请求视为警告或通知而不是错误,则响应状态代码" 304
未修改"和Content-Location
标识现有资源的标头将同样有效.当意图仅仅是为了确保资源存在时,重复请求不会是错误而是确认.请求没有错,但只是冗余,客户端可以引用现有资源.
换句话说,请求很好,但由于资源已经存在,服务器不需要执行任何进一步的处理.