返回 http 200 OK,响应正文中有错误

Returning http 200 OK with error within response body

我想知道当服务器端发生错误时return HTTP 200 OK是否正确(错误详细信息将包含在响应正文中)。

示例:

  1. 我们正在发送 HTTP GET
  2. 服务器端发生意外。
  3. 服务器 returns HTTP 200 OK 响应中有错误的状态代码(例如 {"status":"some error occurred"}

这是正确的行为吗?我们是否应该将状态码更改为 200 以外的其他值?

HTTP 状态代码说明了 HTTP 协议。 HTTP 200 表示 HTTP 级别的传输正常(即请求在技术上正常并且服务器能够正确响应)。有关所有代码及其含义的列表,请参阅 this wiki page

HTTP 200 与您的“业务代码”的成功或失败无关。在您的示例中,HTTP 200 是一个可接受的状态,表示您的“业务代码错误消息”已成功传输,前提是没有技术问题阻止业务逻辑正确 运行。

或者,如果服务器出现技术问题或无法恢复的问题,您可以让您的服务器响应 HTTP 5xx。或者 HTTP 4xx 如果传入请求有问题(例如错误的参数、意外的 HTTP 方法...)同样,这些都表示 技术 错误,而 HTTP 200 表示 没有技术错误,但不保证业务逻辑错误。

总结:是的,在您的 http 响应中发送错误消息(对于非技术问题)以及 HTTP 状态 200 是有效的。这是否适用于您的情况取决于您。例如,如果客户要求一个不存在的文件,那将更像是 404。如果服务器配置错误可能是 500。如果客户要求在已预订满的飞机上找个座位,那将是 200 并且您的“实施”将决定如何 recognise/handle 这个(例如 JSON 块 { "booking": "failed" })

不行,发送200的错误正文是非常不正确的

HTTP 是一种应用协议。 200 意味着响应包含表示所请求资源状态的有效负载。错误消息通常不是该资源的表示。

如果在处理 GET 时出现问题,正确的状态代码是 4xx(“你搞砸了”)或 5xx(“我搞砸了”)。

即使我想 return 一个业务逻辑错误作为 HTTP 代码也没有这样的 该错误的可接受 HTTP 错误代码,而不是使用 HTTP 200,因为它会歪曲实际错误。

因此,HTTP 200 适用于业务逻辑错误。但是 HTTP 错误代码涵盖的所有错误都应该使用它们。

基本上 HTTP 200 意味着什么服务器正确处理了用户请求(如果飞机上没有座位,因为用户请求被正确处理,它甚至可以 return 只是一些座位平面上可用,所以根本不会出现业务逻辑错误或者业务逻辑可以在客户端。业务逻辑错误是抽象的意思,HTTP错误更明确。

澄清一下,您应该在符合协议的地方使用 HTTP 错误代码,而不是使用 HTTP 状态代码发送业务逻辑错误。

诸如余额不足无可用出租车错误user/password等错误符合 HTTP 状态 200 并在响应正文中处理特定于应用程序的错误。

this software engineering answer:

I would say it is better to be explicit about the separation of protocols. Let the HTTP server and the web browser do their own thing, and let the app do its own thing. The app needs to be able to make requests, and it needs the responses--and its logic as to how to request, how to interpret the responses, can be more (or less) complex than the HTTP perspective.

HTTP 是处理互联网数据传输的协议。

如果传输由于某种原因中断,HTTP 错误代码会告诉您无法将其发送给您的原因。

正在传输的数据未由 HTTP 错误代码处理。只有传播方式。

HTTP 不能说 'Ok, this answer is gobbledigook, but here it is'。它只是说 200 OK

也就是说:我已经完成了把它交给你的工作,剩下的就看你了。

我知道已经有人回答了,但我用我能理解的语言表达了它。抱歉重复。

我认为人们过于重视应用程序逻辑与协议问题。重要的是回应应该有意义。如果您有一个服务于动态资源的 API 并且请求 X 是从模板 Y 派生的数据 Z 而 Y 或 Z 当前不可用怎么办?这是业务逻辑错误还是技术错误?正确答案是 "who cares?"

您的 API 和您的回答需要清晰且一致。它应该符合某种规范,并且该规范应该定义什么是有效响应。符合有效响应的内容应产生 200 代码。不符合有效响应的内容应生成 4xx 或 5xx 代码,指示无法生成有效响应的原因。

如果您的规范对有效响应的定义允许 { "error": "invalid ID" },那么它就是一个成功的响应。如果您的规范没有做出这样的调整,return 使用 200 代码响应将是一个糟糕的决定。

我将调用函数打个比方 parseFoo。当你调用 parseFoo("invalid data") 时会发生什么?它 return 是否是错误结果(可能为空)?或者它会抛出异常吗?对于一种方法或另一种方法是否正确,许多人会采取近乎宗教的立场,但最终 这取决于 API 规范。

"The status-code element is a three-digit integer code giving the result of the attempt to understand and satisfy the request"

显然,对于 "successfully returning an error" 是否构成 HTTP 成功或错误存在不同意见。我看到不同的人以不同的方式解释相同的规格。所以选择一方,当然,但也要接受整个世界不会同意你的任何一种方式。我?我发现自己处于中间位置,但我会提供一些常识性考虑。

  1. 如果您的服务器端代码在发送请求时捕获到意外异常,这听起来很像 500 Internal Server Error 的定义。 这好像是OP的情况。应用程序不应 return 出现 200 意外错误, 但也请参阅第 3 点。
  2. 如果您的服务器端代码应该能够优雅地处理给定的无效输入,并且它不构成 "exceptional" 错误条件,那么您的规范 应该 容纳提供有意义诊断信息的 HTTP 200 响应。
  3. 最重要的是:有一个规范。使其一致。坚持下去。

在 OP 的情况下,听起来您有一个事实上的标准,即未处理的异常会产生 200 并具有可区分的响应主体。这并不理想,但如果它不破坏事物并主动引发问题,您可能有更大、更重要的问题需要解决。

我想如果我们想想现实生活,这些问题就迎刃而解了。

不良做法:

示例 1:

Darling everything is FINE/OK (HTTP CODE 200) - (Success):
{
  ...but I don't want us to be together anymore!!!... (Error)
  // Then everything isn't OK???
}

示例 2:

You are the best employee (HTTP CODE 200) - (Success):
{
  ...But we cannot continue your contract!!!... (Error)
  // Then everything isn't OK???
}

良好做法:

 Darling I don't feel good (HTTP CODE 400) - (Error):
{
  ...I no longer feel anything for you, I think the best thing is to separate... (Error)
  // In this case, you are alerting me from the beginning that something is wrong ...
}

这只是我个人的看法,大家可以根据自己的喜好或者需要来实现。

注意:这个解释的想法来自一位好朋友@diosney