处理 http post 时使用哪些 http 状态代码?

Posted

技术标签:

【中文标题】处理 http post 时使用哪些 http 状态代码?【英文标题】:Which http status codes to use when processing http post? 【发布时间】:2021-12-14 18:52:17 【问题描述】:

我有一个 html 表单,我通过 http post 提交。

有两种情况:

案例一:数据有效,服务器上的数据会相应更新 案例 2:数据无效,http 响应包含给用户的错误消息。

每种情况应使用哪些 http 状态码?

我使用htmx 提交表单。这意味着我不需要使用 POST/Redirect/GET 模式。

这个问题与 JSON-API 无关。

【问题讨论】:

不应该是2XX和4XX htmx吗? @tromgy AFAIK 2XX 不是有效的 http 状态代码。这个问题是关于“使用哪个特定的 2xx 和 4xx”状态码。 【参考方案1】:

Mozilla 基金会发布的complete list of HTTP response codes 非常全面且易于阅读,因此我建议您始终将其作为指南进行参考。对于您提到的一般用例,您可以返回几个不同的代码 - 这取决于服务器上的数据发生的情况以及您希望在用户浏览器中发生的情况。

CASE 1:数据有效,服务器数据更新

根据您的简短描述,可能适用的不同状态代码是:

200 (OK):您正在更新您自己服务器上的现有记录 - 例如,用户正在提交更新其在您网站上的现有联系信息的表单 - 并且已收到信息,并且记录更新成功。响应通常会包含更新记录的副本。 201(已创建):您不是在更新现有记录,而是在您的服务器上创建一条新记录 - 例如,您的用户正在将一个新电话号码添加到他们的联系人详细信息中,该电话号码已保存在您的数据库中作为单独的“电话”记录。响应应包含新创建记录的副本。 205(重置内容):与200相同,但表示需要刷新浏览器视图。当正在更新的记录具有由服务器动态计算的值并且可能会根据您提交的值自动更改时,这很有用。例如,如果您有一个用户在他们的在线个人资料中添加额外的信息,这可能会授予他们特殊的身份、徽章和网站上的特权。这意味着,如果用户正在查看他们的个人资料信息,则需要使用服务器自动授予的新“状态”来更新该信息。 205 响应正文通常为空,这意味着要更新浏览器视图,您的响应处理代码需要: 做进一步的 ajax 请求并更新你的相关部分 与来自服务器的新信息交互,或 将用户重定向到一个新的 URL,或者 重新加载整个页面。

如果使用 HTMX,200201 响应将包含您要在页面上更新的记录的实际 html sn-p - 并且 HTMX 将替换当它收到响应时,它会自动为您服务。使用 205 响应,您可以发送 HX-Trigger response header,它会在需要更新自身的界面元素上调用自定义事件 - 请参阅文档中的示例。

CASE 2:数据无效,服务器上的数据没有更新

发生错误时需要返回的状态码取决于导致错误的原因。服务器认为是客户端责任的错误 - 例如“发送无效数据” - 具有 4XX 范围内的状态代码。该范围内的一些常见错误包括 404(“未找到”)、403(“禁止”)和“未经授权”(401)。

如果客户端发送的数据由于“无效”而导致服务器无法处理 - 要么是因为请求本身格式错误,要么是因为数据未通过某些业务验证逻辑 - 当前的建议是返回状态 400(错误请求)

很多年前,有人认为状态码400应该只用于表示格式错误的请求(语法错误),而不是表示业务验证逻辑失败(语义错误)。有很多争论,暂时创建了一个新的状态代码 (422),它应该专门涵盖语义错误。然而,在 2014 年,official definition of the status 400 code 进行了更改,以允许包含语法和语义错误 - 这使得状态 422 基本上没有必要。

你可以在网上找到lots of discussions and explanations关于400422之间的区别,直到今天还有一些人对此争论不休。然而,在实践中,400 代码就是您所需要的全部 - 并且您可以在其中包含一个响应正文,如果需要,可以详细解释错误的原因。

请注意,使用 HTMX 时,带有 400 代码的响应应自动触发 htmx:responseError 事件。例如,您可以捕获该事件以更新您的表单界面元素,以防服务器捕获到数据验证错误。

【讨论】:

感谢您的详细解释。我想我会使用422,因为这样我可以更轻松地检查未捕获错误的统计信息。在我的 htmx 的情况下,我想我不会使用htmx:responseError,因为我想让客户保持愚蠢。如果我可以避免在客户端上进行事件处理,那么我会这样做。如果用户提交了无效的表单数据,那么服务器将再次呈现表单并显示一条消息。这对我来说已经足够了。在这种情况下不需要 JS 事件。再次感谢您的详细回答。【参考方案2】:

嗯,200 OK201 Created 是获得成功的最佳选择。

对于无效数据,我将返回422 Unprocessable Entity,因为标头是正确的,但正文不是(尽管服务器可以解析)。需要注意的是,一些 HTTP 客户端无法正确处理 422,在这种情况下您必须使用 400 Bad Request,但是,大多数现代客户端都可以。

【讨论】:

在我的情况下,422 响应将由 htmx.org 库处理。所以我认为这会很好。然而,哪些网络浏览器不能正确处理 422?我不再需要支持 IE11 或更早版本。 我用简单的网络服务器 while true; do echo -e 'HTTP/1.1 422 Unprocessable Entity\n\ndata\n\r'; | nc -l 8080 -q 1; done 测试了 Edge、Chrome 和 curl,工作正常。 422 的问题可能与旧版 HTTP 客户端有关,但如果您不需要以编程方式访问此端点,它应该没问题。【参考方案3】:

您说过这与 JSON API 无关,但您将如何满足此类要求 - 不清楚这是否与您的场景相关???

服务器驱动的行为

我看不出客户端如何根据输入数据决定 HTTP 状态代码。客户将如何处理这些示例?

调用未经过身份验证(cookie 或令牌) - API 将返回 401 - 这告诉 UI 执行重试操作。

调用未授权 - API 将返回 403 或 404,并且 UI 将显示错误。

根据特定领域的检查,数据格式不正确或无效 - API 会返回 400 并告诉 UI 出了什么问题,以便它可以执行操作。

服务器处理出现问题,例如由于数据库关闭而无法保存数据。

我的想法

htmx 看起来很有趣,但在使用它之前的一个关键要求是确保 htmx 可以读取服务器端错误响应并使用返回的值。也许有一种优雅的方式来做到这一点......

也许我只是偏执狂:)。但在选择没有阻塞问题的技术时,值得小心。在大多数系统中,缺乏错误处理控制将是一个阻塞问题。

【讨论】:

我能理解您的担忧。对我来说,使用 htmx 处理错误非常简单。如果客户端收到 2xx 响应,一切都很好。如果客户端收到 4xx 响应,则表示有一些错误。错误消息在随响应返回的 html 中。我只是不确定要使用哪个特定的 2xx 和 4xx http 状态。我找到了一个不错的解决方案(见上文)。【参考方案4】:

200 OK201 Created 是成功的 POST 请求的最佳选择。

但是,对于无效数据,您可以传递415 Unsupported Media Type

【讨论】:

以上是关于处理 http post 时使用哪些 http 状态代码?的主要内容,如果未能解决你的问题,请参考以下文章

HTTP常用状代码

get和post的方法的区别(HTTP协议的主要方法都有哪些?)

HTTP中GET或PUT方式传body数据

【SpringBoot】http请求注解之Post请求

http之100-continue(转)

检查待处理的 AJAX 请求或 HTTP GET/POST 请求