验证失败或重复无效的REST HTTP状态代码


825

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

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

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

发送状态代码时是否有惯例?



14
打开httpstatus.es,右键单击>> Pin标签:P
Salman von Abbas

Answers:


778

对于输入验证失败:400错误的请求 +您的可选描述。在“ RESTful Web服务 ” 一书中建议这样做。对于双重提交:409冲突


2014年6月更新

相关规范以前是RFC2616,它给出了400(错误请求)的使用范围,

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

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

由于某些原因,服务器无法或将不会处理请求,因为这被视为客户端错误


3
是的,请求主体是语法的一部分。
迪蒙

62
错误的请求绝对是对这种问题的最常见回应。唯一的其他选择是422无法处理的实体。它实际上来自WebDav,但是重用已向IANA注册的任何状态代码是完全有效的。
Darrel Miller

19
那么,如何区分服务器甚至无法解析的格式错误的数据和验证错误?客户将完全不同地处理这两个响应。为了进行验证,他们可能会向用户显示错误。对于真正的“格式错误的数据”,它们将记录错误,因此可以修复生成请求的方法中的错误。
乔什·诺

18
我不同意您对RFC7231的解释,尽管它声明,但something perceived to be a client error本段中给出的所有示例都违反了HTTP协议,而不是逻辑错误:语法,成帧,路由。因此,我认为HTTP规范并没有让400在应用层上验证失败。
Dima Tisnek

2
为什么不使用422-无法处理的实体?对我来说似乎更具逻辑性
java_geek 2014年

278
  • 验证失败:403禁止(“服务器理解了该请求,但拒绝履行该请求”)。与流行观点相反,RFC2616并未说“ 403仅用于失败的身份验证”,而是说“ 403:我知道您想要什么,但我不会那样做”。该条件可能是也可能不是由于身份验证。
  • 尝试添加重复项:409冲突(“由于与资源的当前状态冲突,请求无法完成。”)

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


17
@deamon:这不是规范,而是 Wikipedia,即某人对“ HTTP状态码的含义”的看法;请注意,该页面本质上说:“这是Apache在403中的含义,这是IIS在403中的含义”,并且在任何地方都未引用官方RFC。您似乎在重复“ 403代表Apache所说的一切”。不。实际的RFC(是相关的文档,不是Apache的实现,不是IIS的实现,不是其他任何人的实现):w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvor在

57
“ 10.4.4 403禁止服务器理解了请求,但拒绝执行。授权将无济于事,并且不应重复请求。如果请求方法不是HEAD,并且服务器希望公开为什么请求没有公开完成后,应该描述实体拒绝的原因。如果服务器不希望将此信息提供给客户端,则可以使用状态代码404(未找到)来代替。” 我在那里没有重点(“ SHOULD / SHOULD NOT”是RFC 2119关键字,不是重点);那是您的想法,“禁止”是什么意思,不是RFC的意思。
Piskvor于

10
我喜欢这个答案,但仍然看到一个小问题。根据规范,当返回403时,“不应重复该请求”。但是,返回409 “仅在预期用户可能能够解决冲突并重新提交请求的情况下才允许”。在重复的情况下,我认为403更合适,因为您不能真正解决冲突(除非删除资源的先前实例)。
pablobm 2011年

2
对于错误消息本身,您应该修改原因短语,因此发送标题HTTP/1.0 403 Form validation errors是最干净的方法。
aleemb 2012年

6
IMO 422“不可处理的实体”更有意义。我的理由是,这不是服务器拒绝满足请求,而是服务器无法满足请求。
tybro0103

225

我建议使用状态码422“无法处理的实体”

11.2。422无法处理的实体

422(不可处理实体)状态代码表示服务器理解请求实体的内容类型(因此415(不支持的媒体类型)状态代码不合适),并且请求实体的语法正确(因此400(错误请求) )状态代码不合适),但无法处理其中的说明。例如,如果XML请求主体包含格式正确(即,语法正确)但语义上错误的XML指令,则可能发生此错误情况。


11
当然,这是HTTP状态代码,请参阅iana.org/assignments/http-status-codes。状态代码比RFC 2616中定义的状态代码更多。–
朱利安·雷施克

7
WebDAV是HTTP 扩展。“用于Web分布式创作和版本控制(WebDAV)的HTTP扩展”因此,状态代码422不是http状态代码,而是http部分的状态代码。
迪蒙

16
恶魔,那没有道理。HTTP定义了如何定义新代码,这就是WebDAV所做的。有一个状态码注册表是有原因的。
朱利安·雷施克

14
仅供参考-422的RFC描述:11.2。422不可处理的实体422(不可处理的实体)状态代码表示服务器理解请求实体的内容类型(因此415(不支持的媒体类型)状态代码不合适),并且请求实体的语法正确(因此为400) (错误请求)状态代码不正确),但无法处理其中的指令。例如,如果XML请求主体包含格式正确(即,语法正确)但语义错误的XML指令,则可能发生此错误情况。
史蒂夫·卡列斯塔德

6
而且线程不会“过期”。他们需要保持生存,否则顶级google搜索结果就会变得不准确。
James Billingham 2014年

81

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", ...]
    }
}

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


2
arg之间的交互导致的错误呢?也就是说,arg1有效且arg2有效,但是两者的组合以及发送的特定值无效。
乔纳

1
我不会想太多。只需选择一个看起来拥有该关系的人即可。
sethcall

甚至两个参数都出错。作为用户,我想我想在每个相互冲突的字段上看到错误。
依sn

很好!显性胜于隐性
bhathiya-perera '19

46

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禁止/拒绝访问”可能表示:

  • 需要特殊许可。浏览器可以通过询问用户/密码来处理它。(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."}
}

即使请求在逻辑上失败,Google也会始终在其Geocoding API中返回200作为状态代码:https : //developers.google.com/maps/documentation/geocoding/intro#StatusCodes

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

很简单,HTTP状态代码用于HTTP请求。REST API是Your,请定义您的状态代码。


3
实际上,将HTTP状态代码用于REST会更加令人困惑:1)您在开发人员的工具箱中看到了4xx,而不能一眼看出服务器是返回了合理的值还是根本无法处理您的请求然后2)您所有的错误/异常/捕获处理程序都应检查作为响应返回的服务器(大多数情况下它们不这样做,因为您必须在每个服务调用中都这样做),并且很多时候3)您会获得相同的有效负载(类型)在成功路径和错误路径上都导致复杂/重复的代码……的确非常令人困惑。
szczepanpp

9
这个答案使HTTP协议的原始语义与基于HTTP的REST作为一种体系结构样式如何重新利用HTTP来实现Web服务API 混淆了。作为一种体系结构样式,REST不是严格遵循的标准,它是一种建议的方法。对于验证失败,使用200响应是对还是错,但是这会使您的客户感到困惑,即请求成功了,但实际上是由于验证失败而导致失败,这是响应主体中模糊的一个重要细节,客户必须解析才能理解的语义。
凯文·胡克

5
@Marcodor如果您的API调用失败,但是您返回200表示成功,这是一个好主意吗?尚不清楚,并且会使您的API使用者感到困惑。
凯文·胡克

3
更正的原因有很多,而不仅仅是HTTP与REST错误的分离。REST验证通常需要更多细微差别。例如,由于唯一索引冲突,记录已接受但被标记为重复vs.被拒绝。您还需要一个一致的回报模型。.NET BadRequest()方法具有自己的返回模型,该模型与常规返回模型不同。那是一场噩梦。@KevinHooke,返回HTTP 200以获得REST验证错误,就像在说:“我收到了您的消息,答案是否定的,这就是原因。” 返回HTTP 400时说:“我不知道您在说什么。”
尼尔·拉斯莱特

5
“因为谷歌做到了,它一定是正确的”的论点对我来说很疯狂。它可以挑战谷歌实现了孩子们的东西。对于失败的rest调用返回HTTP 200会使API的调用者感到困惑,它应该是4xx,并且可以在主体中包含漂亮的JSON / XML ...让我们共同避免精神错乱。
杰里尔·库克

43

数据库中的重复项应为409 CONFLICT

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

在这里给出了4xx代码的详细解释。


6

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

在我看来,@ Piskvor的答案是最明显的选择,我认为这是原始问题的意图,但我有另一种选择也很重要。

如果要将重复的请求视为警告或通知而不是错误,则响应状态代码为304未修改,并且Content-Location标头标识现有资源将同样有效。当只是为了确保资源存在时,重复的请求不是错误而是确认。该请求没有错,但只是多余的,客户端可以引用现有资源。

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


6
据我了解,304用于GET操作以辅助缓存。
Sinaesthetic,2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.