当一个 API 请求没能成功的时候,客户端最好能收到一个正确的 HTTP 错误状态,例如 409 或 500,这会是一个好的开始。不幸的是,尽管 400 Bad Request 可能就足够让我们知道错误出在哪里,但常见的情况是我们没有充足的信息来理解或解决实际遇到的问题。
许多 API 会在响应正文中为你提供更多细节,但令人遗憾的是,每个 API 都有自己的定制风格,不同的 API,甚至在各个端点使用的报告样式都不一样。这就需要定制的逻辑或者人工干预才能理解报告的内容。
但这种情况并非无可避免。先不用急着否定我。试着想象一个更好的世界,其中每个 API 都以相同的标准格式返回错误信息。
我们可以用一致的标识符来识别各种类型的错误,并能在任何地方轻松获得清晰的描述和元数据。你的通用 HTTP 客户端可以自动为任何错误提供详尽细节,你的客户端错误处理机制则能轻松可靠地过滤出你所关心的特定错误,并且你能使用单组共享逻辑来处理多种 API 的常见错误。
IETF 提出的 RFC 7807 标准希望定义一个 HTTP API 错误响应的标准格式,从而实现上述目标。它已经开始在现实世界中得到应用了。人们可以很容易地用它来支持现有的 API 和客户端,对于构建或使用 HTTP API 的人来说,这个标准值得关注。
请不要这样做
谈这个问题前,让我们先退一步思考问题。HTTP 的一个关键特性是标准的响应状态代码,例如 200 或 404。正确使用这些代码可确保客户端自动理解响应的总体状态,并根据对应状态采取适当措施。
状态代码对错误处理来说特别有用。当请求收到意外的 500 状态时,几乎所有标准的 HTTP 客户端都会自动为你抛出一个错误,并不需要自定义规则来解析和解释各处的所有响应,从而确保意外错误能被可靠地报告,并可以在任何位置轻松处理。
这是很好的机制,但它也有很大的局限性。
实际上,一个 HTTP 400 响应可能表示以下任何一种情况:
这些全是错误,看起来都是由一个“坏”请求触发的 400 错误,但它们的内容却大相径庭。
状态代码可帮助我们区分错误和成功状态,但没法区分得太细致。因此,HTTP 客户端库不能在抛出的错误中包含任何有用的细节,每个 API 客户端都必须编写自定义的处理机制来解析每个失败的响应,并自行找出可能的原因和下一步应该做的操作。
如果失败的 HTTP 请求自动抛出的异常消息不仅仅是HTTP Error: 400 Bad Request,而是 Credit card number is not valid,这样岂不更好?
只要错误有一套标准格式,上面提到的每个错误就都可以有自己的唯一标识符,并包含标准化的说明内容和指向更多细节的链接。好处是:
为此,RFC7807 提出了一组用于返回错误的标准字段,以及两种将其格式化为 JSON 或 XML 的内容类型。
格式如下:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/transactions/abc"
}
对于 XML 的等效格式:
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="urn:ietf:rfc:7807">
<type>https://example.com/probs/out-of-credit</type>
<title>You do not have enough credit.</title>
<detail>Your current balance is 30, but that costs 50.</detail>
<instance>/account/12345/transactions/abc</instance>
</problem>
这些 RFC 为此定义了两种新的对应内容类型:Application/problem+json或application/problem+xml。返回错误的 HTTP 响应应在其Content-Type响应标头中包含适当的内容类型,并且客户端可以检查该标头以确认格式。
这个示例包括规范定义的一些标准化字段。完整列表是如下:
所有这些字段都是可选的(不过type是强烈建议使用的)。内容类型允许自由包含其他数据,只要它们不与这些字段冲突即可,因此你也可以在此处添加自己的错误元数据,并包含所需的其他任何数据。实例 URI 和类型 URI 都可以是绝对 URI,也可以是相对 URI。
这里的思想是:
目前,这是一个提案的标准,因此它尚未普及,并且在理论上可能会发生变化。
不过它已经用在很多地方,包括 5G 标准之类中,并且有了适用于大多数语言和框架的一些便捷工具,包括:
也就是说,它已经渗透到了大多数主流生态系统中站稳了脚跟,并且即将更进一步:让更多 API 和客户端开始使用,直到实现大规模的普及状态,即大多数 API 的错误格式都遵循其标准,使它成为所有场景的默认值,让我们大家都能从中受益。
我们该如何做到这一点呢?
原文链接:
https://httptoolkit.tech/blog/http-api-problem-details/