【问题标题】:Should I use HTTP 4xx to indicate HTML form errors?我应该使用 HTTP 4xx 来指示 HTML 表单错误吗?
【发布时间】:2013-03-12 22:29:10
【问题描述】:

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

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

我已阅读有关在 REST API 中使用 422(不可处理实体)作为可能的返回代码的信息,但找不到任何证据表明在 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://www.rfc-editor.org/rfc/rfc4918#page-78

11.2. 422 无法处理的实体

422 (Unprocessable Entity) 状态码表示服务器 理解请求实体的内容类型(因此 415(不支持的媒体类型)状态码不合适),并且 请求实体的语法是正确的(因此是 400 (Bad Request) 状态码不合适)但无法处理包含的 指示。例如,如果 XML 请求正文包含格式正确(即语法正确),但是 语义错误的 XML 指令。

[更新 3]

深入研究,422 是一个 WebDAV 扩展[1],这可能解释了它的晦涩难懂。也就是说,由于 Twitter 将 420 用于他们自己的目的,我想我会随心所欲。但它会以 4 开头。

[更新 4]

HTTP 1.1 规范 (https://www.rfc-editor.org/rfc/rfc2616#section-6.1.1) 中关于自定义响应代码的使用以及应如何处理(如果无法识别)的说明:

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

[1]https://www.rfc-editor.org/rfc/rfc4918

【问题讨论】:

  • 这完全取决于您决定如何设计您的 API。我不确定 422 是否是最佳响应代码,但可以肯定的是,您可以发送 4xx 范围内的 200 以外的其他内容。
  • @MattBall 出于兴趣-您为什么不认为这是最好的代码? (我也没有答案——但以 4 开头的东西感觉比 2 好)?
  • 不是直接回答你的问题,而是stackoverflow.com/q/1959947/139010
  • 是的 - 看到那个 - 但不幸的是我不同意接受的答案;-)(请参阅上面问题的更新)。
  • 仅供参考 - RFC2616 已被 RFC7230(和朋友)取代,因此最好参考它们。请参阅 httpwg.org/specs>。此外,虽然 Twitter 最初确实使用 420,但在定义后,他们转向了标准 429。

标签: http


【解决方案1】:

很明显,某些表单 POST 请求会导致 4xx HTTP 错误(例如,错误的 URL、缺少预期的字段、无法发送 auth cookie),但错误输入密码或意外遗漏必填字段在一个应用程序。

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

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

如果客户端脚本使用 HTTP 作为传输机制,情况似乎就更不明确了。例如。如果 JSON-RPC 请求发送表单详细信息,则成功调用服务器端函数并将响应返回给调用者,看起来像 200 成功。

有趣的是:使用错误凭据登录会在 Facebook、Google 和 Wikipedia 上产生 200,而在 Amazon 上会产生 204。

理想情况下,IETF 会使用 RFC 来解决这个问题,可能会添加一个 HTTP 错误代码以表示“由于表单失效失败而未执行操作”或扩展 422 的定义以涵盖这一点。

【讨论】:

  • 这并不明显,因此问题。
【解决方案2】:

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

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

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

【讨论】:

  • 我对 422 的保留只是它不在最初的 W3C 规范中,而是一个 WebDAV 扩展。我选择 421 的原因是 422 是最接近的现有代码,而 420 是 Twitter 的编造代码,因此介于两者之间似乎合适。
  • 另外——虽然我得到了“不要去发明你自己”的情绪——实际上最坏的情况是什么(这是一个真正的问题,我不是在挑衅)。
  • a) HTTP/1.1 是 IETF 规范,而不是 W3C 规范 b) 该规范没有列出所有状态代码,在 iana.org/assignments/http-status-codes/http-status-codes.xml 有一个注册中心 c) 事实上定义与 WebDAV 规范无关; 422 是一个通用的状态码。 d) 最坏的情况是别人定义了421,让它流行起来,它的定义和你的冲突。顺便说一句,它刚刚发生在状态代码为 308 的 Google 身上。
  • 谢谢 - iana 列表是一个很好的资源 - 非常有帮助。
  • (仅供参考 - 对于我们的具体情况,我坚持使用 421 - 但我对任何下游未来问题承担全部责任;-))
【解决方案3】:

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

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

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

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 2013-01-31
      相关资源
      最近更新 更多