REST API - 用于预订的 Http 状态代码 API?

REST API - Which Http status codes to use for a booking API?

我对我正在构建的 API 的 return 哪些 HTTP 状态代码有点困惑。 API 允许客户查询产品库存并进行租赁预订。

问题是在以下类似情况下什么时候使用 400s 什么时候使用 200s:

  1. 最终用户发出了有效的预订请求,但他们请求的项目在他们选择的日期都已预订一空。
  2. 最终用户提出了有效的预订请求,但订单日期太早了。关键信息:我们需要至少提前两天通知才能完成订单。
  3. 最终用户在第一次预订后的一天尝试呼叫我的 {orderId}/confirm 端点。关键信息:您必须在预订后 15 分钟内确认订单,否则将超时。

请求的格式正确,引用的资源都存在,难道真的是客户端错误吗?如果不是,那么 return 400 个代码是否合适?

在这些情况下您会使用哪个 HTTPStatus? 200 多岁还是 400 多岁?

老实说,REST 在 Web 上是一团糟,你会看到 API 会 return 200 出现应用程序层错误,而 API 会 return 400 类似于你的例子。检查您的选择是否会影响是否可以缓存响应总是好的,但我假设您无论如何都会 POSTing 到这些端点。

就我个人而言,我会推荐 gRPC 采用的方法,即对应用程序和协议错误使用相同的 status,这在大多数 API 中感觉非常一致。通读那里的错误类型可能有助于了解什么应该是错误,什么应该是正常的,但根据经验,200 OK 应该始终表示“我已满足您的要求”。

另请注意 HTTP RFC 表示:

o 4xx (Client Error): The request contains bad syntax or cannot be fulfilled

o 5xx (Server Error): The server failed to fulfill an apparently valid request

500 space 通常被解释为“这应该有效,但没有,因为我们搞砸了(技术问题)”,所以你所有的例子都应该是 400s,如果你 return 它们作为 HTTP 代码。

我很好奇是否有人会持反对意见,但在我看来,使用应用程序错误有点奇怪,因为您现在必须进行双重错误检查和逻辑操作:

if (response.getHttpStatus() != HttpCode.OK) {
  handleHttpError();
} else if (response.getPayload().getStatus() != PayloadCode.OK) {
  handleApplicationError();
}
doWork(response.getPayload());

我认为这是合理的,但如果您使用的框架以一种奇怪的方式使用 HTTP 错误会导致问题,因为框架 400 需要与应用程序 400 不同的处理方式。

实际上,(不是惯用语)说它分解为您的偏好。我会在等式中添加以下问题:

  1. 您将如何根据服务器的“错误”响应在客户端上分支您的逻辑?假设您有几种情况:

    • 特定位置的请求日期已预订(如您所述)
    • 请求的日期可用但非常有限。因此,来自不同地方的两个用户尝试同时预订同一个地方 -> 一个出现错误。
    • 区域内的所有位置都被预订一空 ...(你可以想出更多)

    所有这些都需要有不同的错误代码,以便在 UI 中显示不同的错误消息并用于“跟踪目的”(也许您看到某些位置在特定时间非常繁忙,例如显示类似于“此时书籍很快”)。在响应主体中包含特定于应用程序的内部代码非常重要,这样 UI 才能采取相应的行动。

  2. 您如何从可观察性的角度跟踪这些错误?你可以说我们所有请求的 95% 都会导致“200”响应。这是什么意思?我会按如下方式阅读:“业务逻辑”大部分时间都能正常工作。 5% 是需要修复的意外错误(用户输入的带有非 ASCII 符号的位置以某种方式破坏了您的验证等)。相反,如果您看到只有 50% 的响应是“200”,这可能会带来混淆,尽管您的业务逻辑是正确的,对吧?你能做些什么来解决用户输入“不可用”日期的问题? 但是,即使对业务逻辑使用 HTTP 错误代码,也可以调整这部分可观察性以正确显示您需要的数据。

您可能会从上面的陈述中猜到,我更喜欢将 HTTP 错误代码用于非业务逻辑。它也使事情变得清晰,虽然起初有点违反直觉,因为使用 200 表示不成功的行为。但最终,由您来决定。只需确保您与错误代码保持一致,并充分理解 produce/treat 它们在 server/client 方面的方式。

Which Http status codes to use for a booking API?

HTTP 状态代码属于 transfer of documents over a network 域。因此,您使用它们的方式与万维网上所有其他服务器使用它们的方式完全相同。

The status-code element is a 3-digit integer code describing the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message is to be interpreted in light of the semantics defined for that status code.

特定于您的域的语义不属于 HTTP headers,而是属于响应的消息 body。

遵守 REST 架构约束的有用启发式方法:您将如何在 Web 上做到这一点?通常,您打算为人类(理解域上下文的客户端)提供的信息属于 HTML,也就是说 HTTP 响应的 body。元数据(状态代码,headers)为对文档内容不感兴趣的通用组件(浏览器、缓存,web-crawlers)提供语义提示。

The question is when to use 400s and when to use 200s in the following similar situations

考虑 cache-invalidation 的规则可能会有所帮助。 TL;DR 是如果您发送错误状态代码(4xx 或 5xx),那么缓存知道响应 body 是错误的表示,并且 先前缓存的资源副本仍应被视为有效.

另一方面,2xx 代码报告请求确实成功更改了资源,因此先前缓存的资源副本可能会失效。

POST /orders/12345 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

confirm=yes

如果此消息更改了 /orders/12345 资源,那么您应该倾向于返回 2xx 响应,即使对文档的更改并未反映您域中的“快乐路径”。另一方面,如果资源不变,则 4xx 代码更合适。

status code registry 个文档,其中当前定义了每个状态代码的语义。您可以深入了解每个标准,以了解每个标准的不同含义和含义。

但简而言之,有两个 4xx 代码很突出:

  • 403,表示服务器理解请求但拒绝执行。
  • 409,表示由于资源的当前状态,服务器无法完成请求。

我在标准中没有发现任何区别对待这两个代码的地方。

我认为您可以提出一个论点,即 409 邀请客户获取资源的新副本,合并更改,然后重新提交 - 与 401 邀请客户重新提交请求的方式大致相同授权凭据。但我从未听说过有通用组件可以做到这一点。也许有点遥不可及。