每当我在基于Django/活塞的REST API应用程序中遇到验证失败时,我都会返回401 Unauthorized。 已经看了HTTP状态代码注册表 我不相信这是一个合适的代码验证失败,你们都建议什么?

400错误请求 401年未经授权 403年被禁止的 405方法不允许 406不可接受 412前置条件失败 417期望失败 422不可处理实体 424依赖失败

更新:上述“验证失败”是指应用程序级别的数据验证失败,即错误指定日期时间、伪造电子邮件地址等。


在记录HTTP 1.1的RFC 2616中有关于这些错误语义的更多信息。

就我个人而言,我可能会使用400个坏请求,但这只是我个人的观点,没有任何事实支持。


你说的“验证失败”到底是什么意思?你在验证什么?你指的是语法错误(比如格式错误的XML)吗?

如果是这样的话,我认为400个坏请求可能是正确的,但如果不知道你正在“验证”的是什么,就不可能说出来。


我想说,从技术上讲,这可能不是HTTP故障,因为资源(假设)是有效指定的,用户是经过身份验证的,并且没有操作故障(然而,即使规范也包括一些保留代码,如402 Payment Required,严格来说也不是与HTTP相关的,尽管在协议级别上可能是可取的,这样任何设备都可以识别这种情况)。

如果确实是这样,我将在响应中添加一个带有应用程序错误的状态字段,例如

<status><code>4</code><message>日期范围无效</message></status>


如果“验证失败”意味着请求中有一些客户端错误,那么使用HTTP 400(坏请求)。例如,如果URI应该具有ISO-8601日期,而您发现它的格式错误或指向2月31日,那么您将返回HTTP 400。同样,如果您希望实体主体中有格式良好的XML,但它无法解析。

(1/2016):在过去的五年里,WebDAV更具体的HTTP 422(不可处理实体)已经成为HTTP 400的一个非常合理的替代方案。参见它在JSON API中的使用实例。但是请注意,HTTP 422还没有进入HTTP 1.1, RFC-7231。

Richardson和Ruby的RESTful Web服务包含了一个关于何时使用各种HTTP响应代码的非常有用的附录。他们说:

400(“错误请求”) 重要性:高。 这是一般的客户端错误状态,当没有其他合适的4xx错误代码时使用。它通常用于客户端提交一个表示和 PUT或POST请求,并且表示形式是正确的格式,但是它没有使 任何有意义的。(381页)

and:

401(“未经授权的”) 重要性:高。 客户端试图操作受保护的资源,但没有提供适当的身份验证凭据。它可能提供了错误的凭证,或者根本没有提供。 凭证可以是用户名和密码、API密钥或身份验证 令牌——不管服务期望什么。这对客户来说是很常见的 一个URI请求,并接受401,这样它就知道要发送什么样的凭据 以及什么样的格式。[…]


来自RFC 4918(也在http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml):上有文档

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.


数据库中的副本应该是409冲突。

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

我在这里对4xx代码给出了更详细的解释:http://parker0phil.com/2014/10/16/REST_http_4xx_status_codes_syntax_and_sematics/


下面就是:

rfc2616#section-10.4.1 - 400错误请求

由于格式错误,服务器无法理解请求 语法。客户不应该在没有修改的情况下重复请求。

Rfc7231 #章节-6.5.1 -6.5.1。400错误请求

400(坏请求)状态码表示服务器不能 或者由于感知到某些东西而不处理请求 客户端错误(例如,格式错误的请求语法,无效的请求消息框架,或欺骗性的请求路由)。

是指畸形(不完善)的情况!

Rfc4918 - 11.2。422不可处理实体

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

结论

经验法则:[_]00涵盖了最常见的情况和指定代码未涵盖的情况。

422适合最好的对象验证错误(正是我的建议:) 至于语义错误——想想类似“这个用户名已经存在”的验证。

400被错误地用于对象验证


如果你正在验证数据,而数据不是,根据定义的规则,最好发送422(不可处理实体),这样发送方就会明白他违反了约定的规则。

坏请求是语法错误。有些工具,如postman,会提前显示语法错误。


下面是要讨论的另一个有趣场景。

What if its an type detection API that for instance accepts as input a reference to some locally stored parquet file, and after reading through some metadata of the blocks that compose the file, may realize that one or more of the block sizes exceed a configured threshold and therefor the server decided the file is not partitioning correctly and refuses to start the type detection process. This validation is there to protect against one of two (or both) scenarios: (1) Long processing time, bad user experience ; (2) Server application explodes with OutOfMemoryError

在这种情况下,什么才是适当的回应?

400(错误请求)?-大体上是这样的。

401(未经授权,即未经认证)?——无关。

403(禁止即未经授权)?-有些人会认为在这种情况下可能有点合适-

422(不可处理实体)?-许多旧的答案提到这是输入验证失败的适当选项。在我的情况下使用它让我感到困扰的是这个响应代码的定义说它是“由于语义错误”,而我不太理解语义错误在这种情况下意味着什么,以及我们是否可以将此失败视为语义错误失败。

此外,所谓的简单概念“输入”作为“输入验证”的一部分,在这种情况下,客户端提供的物理输入只是一个指针,一个对存储在服务器中的实体的引用,其中实际的验证是对存储在服务器中的数据(parquet文件元数据)以及客户端试图触发的操作(类型检测)进行的。

413 (PayloadTooLarge) ?通过不同的代码,我遇到了一个可能适合我的情况,一个到目前为止没有人在这里提到的,那是413 PayloadTooLarge,我也想知道它是否适合,或者再次,不,因为它不是在请求中发送的实际有效载荷太大,而是存储在服务器中的资源的有效载荷。

这让我想到,也许5xx的回复在这里更合适。

507存储空间不足?如果我们说“存储”就像“内存”,如果我们还说我们在这里快速失败,声称我们没有足够的内存(或者我们可能会因为内存耗尽而崩溃)来处理这项工作,那么也许507是合适的。但事实并非如此。

我的结论是,在这种服务器由于时空相关限制而拒绝对资源调用操作的场景中,最合适的响应是413 PayloadTooLarge