【问题标题】:Rest API Localization - Headers vs PayloadRest API 本地化 - 标头与有效负载
【发布时间】:2021-10-25 22:04:32
【问题描述】:

我们有一个正在生产中的 POST API。现在我们需要接受本地化信息并相应地继续执行。 例如如果 distanceUnit 为“KM”,则以公里为单位处理所有传入数据。

我可以想到三个选项来接受本地化信息。

  1. 作为 http 标头,即本地化:{"distanceUnit": "km"}
  2. 作为有效载荷本身的一部分。
  3. 请求参数。

我喜欢第一个选项

  • 它不会更改 api 合同。
  • 其他 api 更容易发送此信息,以防将来需要本地化。
  • 本地化是内容协商的一部分,所以我认为它不应该是有效负载/查询参数的一部分。

这里的任何意见都有助于将第一个或第二个选项归零。

谢谢。

【问题讨论】:

标签: rest


【解决方案1】:

虽然 accept-language(如建议的链接 Kit 所发布的那样)可能正在尝试,但它仅支持由 IANA 维护的 registered languages,网络的标准化团体,但不支持某些开箱即用的通用配置选项。它可能会尝试默认为miles,即Accept-Language: us,并在其他地方使用km,如果美国科学家想使用km而不是miles,您的应用程序可能会遇到某些问题。但如果情况并非如此,那么这显然是您可以考虑的一个选择。关于自定义 HTTP 标头,我不建议使用这些,因为自定义 HTTP 标头的问题通常是任意通用 HTTP 客户端不支持这些,这在某种程度上与应该使用 REST 架构的想法相矛盾。

让我们将您的问题转移到 Web 域,看看我们通常如何在那里解决该任务。由于 REST 基本上只是我们人类与 Web 交互的常见方式的一种通用方法,因此 Web 上使用的任何概念也适用于 REST 架构。因此,将整个交互流程设计为就像您的应用程序在典型网页上进行交互一样只是常见做法(或至少应该如此)。

在 Web 上,所谓的Web form 用于“教”Web 客户端(也称为浏览器)服务器期望作为输入的数据。它不仅教客户端关于服务器期望或支持特定资源的相应属性,还教客户端使用哪种 HTTP 方法,关于将请求发送到的目标 URI 以及关于要使用的媒体类型,这通常是隐含的只是作为application/x-www-form-urlencoded 给出,但也可能是multipart/form-data。

表单和链接的使用属于 HATEOAS 约束,其中这些 concpets 允许客户完成他们的任务,即在网上商店购买商品或管理系统中的用户,而无需咨询外部文档。这里的应用程序基本上只是使用内置的超媒体功能来完成他们的任务。客户端通常遵循某种predefined processes,其中服务器指示客户端他们需要做什么才能将商品添加到购物车或如何添加或编辑用户,同时仍然只是在通用 HTML 文档上进行操作本身并不适合手头的相应任务。这种方法允许 Web 客户端基本上呈现各种页面,并且用户可以与这些通用页面进行交互。如果该页面表示中的某些内容发生更改,您的浏览器将自动适应并在下一次请求时呈现新版本。因此,系统能够随着时间的推移而发展并轻松适应变化。这可能是任何人基本上都想使用 REST 架构的核心原因之一。

那么,回到主题。在 Web 上,服务器会向客户端宣传它支持具有上述形式的各种本地化信息。可能会向用户呈现一个选项或下拉选项,其中她/他可以选择适当的选项。用户通常根本不关心这个输入是如何传输到服务器的,或者根本不关心服务器的内部结构。她/他所关心的是在提交请求后数据将可用(在添加或更新资源的情况下)。这也适用于 REST 架构中的应用程序。

您可能会在这里看到一个模式。 REST 和可浏览的 Web 基本上是一回事。后者虽然侧重于人机交互,而入门者应该允许应用程序“网上冲浪”和follow allong processes outlined by the server(半)自动。因此,现在应该很清楚,适用于可浏览 Web 的相同概念也适用于 REST 和该 REST 架构中的应用程序。

我喜欢第一个选项,因为它不会改变 api 合约

客户端不应绑定到特定的 API,因为这会产生耦合,REST 会不惜一切代价避免这种情况。除了直接绑定到 API,Web 以及 REST 也应该使用contracts build on hyper media types,它定义了所交换消息的可接受语法和语义。通过将合约从 API 本身抽象为媒体类型,客户端可以同时支持各种合约。媒体类型的泛化还允许即用相同的媒体类型表达各种不同的事物,从而增加重用的可能性,从而更好地支持应用层的集成。

支持各种媒体类型类似于说不同的语言。通过能够说各种语言,您只会增加您能够开箱即用地与其他人(服务)交流的可能性,而无需之前学习这些语言。客户端可以通过Accept 标头告诉服务器它能够“说”哪些媒体类型((也称为进程),服务器将响应其中任何一个或响应406 Not Acceptable。该错误响应是,正如 Jim Webber 所说,coordination data 始终告诉您是否一切顺利,或者在出现故障时会向您反馈问题所在。

因此,为了保持面向未来,我建议围绕支持表单的超文本媒体类型(即 HTML 表单、applicaiton/hal-forms+json 或 application/ion+json)设计配置。如果将来您需要添加更多配置选项,添加这些只是一项微不足道的任务。该配置是否公开为您只是链接到的自己的资源,作为资源中的嵌入部分或根本不返回给客户端也是您可以选择的。如果相同的配置可能被多个资源使用,那么将其公开为自己的资源,然后创建从资源到该配置的引用是有益的,但如上所述,这些是您必须做出的设计决策。

【讨论】:

    【解决方案2】:

    如果 POST 请求正文是唯一使用它的地方,并且您不必执行 GET 请求并自动应用任何转换,我的偏好可能是将其添加到正文中。

    很高兴有一个包含所有信息的完整文档来描述自己,而不需要外部带外数据来完全解释其含义。

    您可能希望将架构定义为始终将单元包含在文档的相关部分中,例如:

    distance: [5, 'km']
    

    或者,如您所说,在文档顶部执行一次。

    【讨论】:

      猜你喜欢
      • 2018-01-26
      • 1970-01-01
      • 2019-04-03
      • 2017-06-22
      • 2021-09-14
      • 1970-01-01
      • 2019-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多