我应该使用HTTP 4xx来指示HTML表单错误吗?

时间:2013-03-22 22:38:56

标签: http

我花了20分钟调试一些(django)单元测试。我正在测试一个视图POST,我期待一个302返回代码,之后我断言了一堆数据库实体正如预期的那样。原来最近合并的提交添加了一个新的表单字段,我的测试失败了,因为我没有包含正确的表单数据。

问题是测试失败了,因为HTTP返回代码是200而不是302,我只能通过打印响应HTTP并查看它来解决问题。除了必须通过HTML来解决问题的烦恼之外,200似乎是一个没有得到处理的POST的错误代码。 4xx(客户端错误)似乎更合适。此外,它会使测试变得简单,因为响应代码会直接指出我的问题。

我已经阅读过使用422(不可处理实体)作为REST API中可能的返回代码,但无法找到在HTML视图/处理程序中使用它的任何证据。

我的问题是 - 是否有其他人这样做,如果没有,为什么不呢?

[更新1 ]

为了澄清,这个问题与HTML表单有关,而不是API。

这也是关于HTTP响应代码本身的问题 - 而不是Django。这恰好就是我正在使用的东西。我删除了django标签。

[更新2 ]

进一步澄清,W3C引用(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html):

  

10.2成功2xx

     

此类状态代码表示客户端的请求已成功接收,理解和接受。

     

10.4客户端错误4xx

     

4xx类状态代码适用于客户端似乎有错误的情况。

     

10.4.1 400错误请求

     

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

来自https://tools.ietf.org/html/rfc4918#page-78

  

11.2。 422无法处理的实体

     

422(不可处理实体)状态代码表示服务器      了解请求实体的内容类型(因此a      415(不支持的媒体类型)状态代码不合适),和      请求实体的语法是正确的(因此是400(错误请求)      状态代码不合适但是无法处理包含的内容      说明。例如,如果是XML,则可能会出现此错误情况      请求正文包含格式正确(即语法正确),但是      语义错误的XML指令。

[更新3 ]

深入研究,422是WebDAV扩展[1],这可能解释其默默无闻。也就是说,由于Twitter为了自己的目的使用420,我想我会满足于我想要的任何东西。但它将以4开头。

[更新4 ]

有关使用自定义响应代码的说明,以及如何从HTTP 1.1规范(http://tools.ietf.org/html/rfc2616#section-6.1.1)处理它们(如果无法识别):

  

HTTP状态代码是可扩展的。不需要HTTP应用程序      了解所有已注册状态代码的含义,尽管如此      理解显然是可取的。但是,申请必须      了解任何状态代码的类,如第一个所示      数字,并将任何未被识别的响应视为等同于      x00该类的状态代码,但有一个例外      无法识别的响应绝不能被缓存。例如,如果是      客户端收到无法识别的状态代码431,它可以      安全地假设它的请求有问题      将响应视为已收到400状态代码。在这样的      例如,用户代理应该向用户提供返回的实体      有回应,因为该实体可能包括人 -      可读信息,解释不寻常的状态。

[1] https://tools.ietf.org/html/rfc4918

4 个答案:

答案 0 :(得分:2)

如果结果不成功,你说对200是错的。

我还认为成功 - 重定向到结果页面应该是303,而不是302.

4xx对于客户端错误是正确的。 422对我来说似乎是对的。在任何情况下,如果没有通过IANA注册,请不要发明新的4xx代码。

答案 1 :(得分:1)

似乎没有一个公认的答案,说实话,有点令人惊讶。表单验证是Web开发的基石,事实上没有响应代码来说明验证失败,这似乎是错失的机会。特别是考虑到自动化测试的激增。通过检查错误消息的HTML内容而不是仅测试响应代码来测试响应似乎不切实际。

我坚持认为200是对业务规则失败的请求的错误响应代码 - 而且302也是不合适的。 (如果表单验证失败,那么它不应该更新服务器上的任何状态,因此是幂等的,并且不需要使用PRG模式来阻止用户重新提交表单。让他们。)

因此,鉴于没有“已批准”的方法,我目前正在测试(字面上)我自己的 - 421.如果我们遇到使用非标准HTTP状态代码的任何问题,我会报告。

如果这个答案没有更新,那么我们在制作中使用它,它可以工作,你也可以这样做。

答案 2 :(得分:1)

很明显,某些形式的POST请求会导致4xx HTTP错误(例如错误的URL,缺少预期的字段,无法发送auth cookie),但错误输入密码或意外省略必填字段是非常常见的应用程序中的预期事件。

从任何规范中都不清楚每个表单无效问题都必须构成HTTP错误。

我想我的直觉是,如果服务器向客户端发送一个表单,并且客户端立即使用所有预期字段向该表单发出正确形成的POST请求,那么常见的业务逻辑违规不应该是HTTP错误。

如果客户端脚本使用HTTP作为传输机制,则情况似乎更少定义。例如。如果JSON-RPC请求发送表单详细信息,则成功调用服务器端函数并将响应返回给调用者,这似乎是200次成功。

有趣的是:使用糟糕的凭据登录会产生来自Facebook,Google和维基百科的200,以及来自亚马逊的204。

理想情况下,IETF会使用RFC清除这一点,可能会为&#34添加HTTP错误代码;由于表单无效失败而未执行操作"或者扩展422的定义以涵盖这一点。

答案 3 :(得分:-1)

如果您不重定向,POST将返回200。 在POST请求之后,302不会在标头中自动发送,因此您必须手动发送标头(https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponse),并且代码不会在表单数据中转发。

使用代码302重定向回到表单(或其他)的原因是禁止浏览器在刷新或历史浏览时重复发送数据。