我正在使用基于rest的API构建一个应用程序,并且已经到了为每个请求指定状态代码的地步。
我应该发送什么状态代码的请求失败验证或请求试图添加一个副本在我的数据库?
我已经在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上找过了,但是没有一个是对的。
发送状态码时有什么惯例吗?
我正在使用基于rest的API构建一个应用程序,并且已经到了为每个请求指定状态代码的地步。
我应该发送什么状态代码的请求失败验证或请求试图添加一个副本在我的数据库?
我已经在http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html上找过了,但是没有一个是对的。
发送状态码时有什么惯例吗?
当前回答
我得出的结论是尝试遵循这个规则:如果它表明客户端开发人员错误,那么使用400(坏请求)。否则,假设根本没有客户端验证,如果哑用户输入无效数据,则使用422(不可处理实体)。如果有疑问,最好使用422,或者使用更容易实现的版本。
这有助于开发人员了解到底是谁犯了错误,是他自己还是用户。
所谓笨用户,我指的是非技术用户。攻击者在这里不重要:如果您担心这个问题,您就不会首先使用HTTP状态码。:)
例如,如果您正在根据JSON模式验证JSON请求体,400是正确的选择(例如缺少键,关键字不匹配)。但是,如果您希望用户输入一个有效的电子邮件,那么您应该使用422(让我再说一遍,假设没有客户端验证)。
这对更好的分支逻辑也很有帮助。例如,在REST API的上下文中,假设您有一个调查响应端点,可能使用POST和PATCH方法。在这种情况下,如果客户端发送了一个无效的POST请求,您可能希望在Location报头中返回新资源的URI,用于状态码为422时,而不是用于400时。
真实世界的例子当然更复杂,但我认为这应该很管用。
其他回答
我得出的结论是尝试遵循这个规则:如果它表明客户端开发人员错误,那么使用400(坏请求)。否则,假设根本没有客户端验证,如果哑用户输入无效数据,则使用422(不可处理实体)。如果有疑问,最好使用422,或者使用更容易实现的版本。
这有助于开发人员了解到底是谁犯了错误,是他自己还是用户。
所谓笨用户,我指的是非技术用户。攻击者在这里不重要:如果您担心这个问题,您就不会首先使用HTTP状态码。:)
例如,如果您正在根据JSON模式验证JSON请求体,400是正确的选择(例如缺少键,关键字不匹配)。但是,如果您希望用户输入一个有效的电子邮件,那么您应该使用422(让我再说一遍,假设没有客户端验证)。
这对更好的分支逻辑也很有帮助。例如,在REST API的上下文中,假设您有一个调查响应端点,可能使用POST和PATCH方法。在这种情况下,如果客户端发送了一个无效的POST请求,您可能希望在Location报头中返回新资源的URI,用于状态码为422时,而不是用于400时。
真实世界的例子当然更复杂,但我认为这应该很管用。
对于输入验证失败:400坏请求+您的可选描述。这在“rest式Web服务”一书中得到了建议。 对于双重提交:409冲突
2014年6月更新
相关的规范曾经是RFC2616,它给出了400(坏请求)的使用范围相当狭窄
由于语法错误,服务器无法理解请求
因此,可能有人认为它不适用于语义错误。但现在不是了;自2014年6月起,相关标准RFC 7231取代了之前的RFC2616,更广泛地使用400(坏请求)
服务器不能或 将不会处理请求由于某些东西被认为是 客户端错误
数据库中的副本应该是409冲突。
我建议使用422 UNPROCESSABLE ENTITY来处理验证错误。
我在这里对4xx代码做了更详细的解释。
状态代码304 Not Modified也会对重复的请求做出可接受的响应。这类似于使用实体标记处理If-None-Match的报头。
在我看来,@Piskvor的答案是更明显的选择,我认为是原始问题的意图,但我有一个替代方案,也是相关的。
如果希望将重复请求视为警告或通知,而不是错误,响应状态码304 Not Modified和标识现有资源的Content-Location头同样有效。当意图仅仅是确保资源存在时,重复的请求将不是错误,而是确认。请求并不是错误的,只是多余的,客户端可以引用现有的资源。
换句话说,请求是好的,但是由于资源已经存在,服务器不需要执行任何进一步的处理。
Ember-Data的ActiveRecord适配器期望从服务器返回422个UNPROCESSABLE ENTITY。所以,如果你的客户端是用Ember.js编写的,你应该使用422。只有这样DS。错误将用返回的错误填充。当然,您可以将422更改为适配器中的任何其他代码。