【问题标题】:How to offer lists of valid values for parameters in a RESTful API?如何为 RESTful API 中的参数提供有效值列表?
【发布时间】:2016-10-31 21:59:59
【问题描述】:

我猜,这更像是一个概念问题而不是技术问题。假设我有一个 REST API 来处理庞大的租车车队。

API 以非常标准和连贯(即使有争议)的方式围绕业务实体/资源建模:

  • /cars/1234 - 某辆车的详细数据
  • /clients/5678 - 关于某个客户的详细数据
  • /cars - 汽车及其 URI 列表
  • /clients - 客户列表

但是,车队规模庞大,列出所有汽车的清单并没有多大用处。我宁愿过滤它,比如:

GET /cars?type=minivan

为了正确使用“type”参数,我应该有一个有效值列表,例如“minivan”、“convertible”、“station-wagon”、“hatchback”、“sedan”等。好的,那里没有那么多种类的汽车,但是让我们假设这个列表对于 API 的 Swagger 定义中的枚举来说太大了。

那么...对于 REST API 来说,为这样的查询参数提供有效值列表的最一致和自然的方式是什么?

  • /cars/types 这样的从属资源?这会破坏/cars/{id} URL 模式,不是吗?

  • 作为单独的资源,例如/tables/cars/types?这会破坏商业模式本身主要资源的一致性,对吗?

  • 作为OPTIONS /cars 响应正文的一部分?对我来说,这看起来像是“最完整”的方式,但我的一些同事不同意,而且 OPTIONS 似乎很少用于这样的事情。

  • 也许作为对GET /cars?&metadata=values 或类似内容的回复的一部分?这里的“值”在语义上似乎与返回的数据相关,而不是查询参数,不是吗?

  • 还有别的吗?

我在 SO 中搜索并搜索了一些关于这个特定主题的建议,但我找不到任何可以帮助我为这样的决定提供论据的东西......

谢谢!

法布里西奥·罗查

巴西利亚,巴西

【问题讨论】:

    标签: web-services rest


    【解决方案1】:

    “一个好的 REST API 就像一个丑陋的网站”——Rickard Öberg

    那么你将如何在网站上做到这一点?好吧,您可能有一个指向表单的链接,并且该表单将有一个列表控件/单选按钮,其中包含每个选项的语义提示,期望用户从可用选项中选择一个值,并且提交表单时,用户代理会将该值编码到 GET 请求的 URL 中。

    所以在 REST 中,你做同样的事情。在最初的回复中,您将包含一个指向您的“表单”资源的链接;当用户代理获取表单资源时,您返回表单的超媒体表示,其中编码了可用的选项,当提交表单时,您的资源从标识符的查询部分中选择客户端选项。

    但您可能没有使用 REST:它是一个巨大的 PITA,REST 架构约束的好处可能不会在您的上下文中得到回报。因此,您可能只是在为返回带有选项列表的消息的资源寻找合理的标识符拼写。

    作为像 /cars/types 这样的从属资源?这会破坏 /cars/{id} URL 模式,不是吗?

    假设您的路由实现可以处理歧义,这是一个不错的选择。您可能会考虑是否只有一个列表,或者针对不同上下文的不同列表,以及如何处理。

    作为单独的资源,例如 /tables/cars/types?这会破坏业务模型本身主要资源的一致性,对吗?

    还记得 OO 编程和封装吗?将 API 与底层数据模型解耦是一件好事。

    也就是说,我个人不喜欢将“表格”作为层次结构中的一个元素。如果您想朝这个方向发展,我建议您使用/dimensions——如果您正在设计data warehouse,这是您可能使用的拼写

    作为 OPTIONS /cars 响应正文的一部分?对我来说,这看起来像是“最完整”的方式,但我的一些同事不同意,而且 OPTIONS 似乎很少用于这样的事情。

    哎呀! RFC 7231 提出了一个非常令人困惑的想法。

    OPTIONS 方法请求有关目标资源可用的通信选项的信息,无论是在源服务器还是中​​间中介。

    (强调添加)。在为 Web 编写 API 时,您应该始终牢记,客户端请求可能会通过您无法控制的中介;您在这些情况下提供良好体验的能力取决于不会因偏离统一界面而混淆中介。

    也许作为对 GET /cars?&metadata=values 或类似内容的响应的一部分?

    在大多数情况下,机器对任何拼写都很满意。 URI 设计指南通常侧重于人类受众。我认为特定的拼写会使您的人类消费者感到困惑,特别是如果 /cars?... 会以其他方式识别资源是搜索结果。

    还有什么?我仍然觉得人们期望在 /cars 下找到的是...一堆汽车(我的意思是它们的表示),而不是其中的值列表...

    所以让我们稍微改变一下你的问题

    对于这样的查询参数记录有效值列表的 REST API 最一致和最自然的方式是什么?

    如果网络真的有什么好处的话,那就是记录的东西。选择几乎所有有据可查的 Web API,并仔细注意您在哪里阅读有关端点的信息——这会给您一些好主意。

    例如,您可以查看 StackExchange API,其中

    https://api.stackexchange.com/docs/questions

    告诉您所有您需要了解的有关资源系列的所有信息

    https://api.stackexchange.com/2.2/questions

    不出所料,类型的记录如下:

    https://api.stackexchange.com/docs/types/flag-option

    如果你想变得性感,可以使用 Accept-Type 协商重定向到人类可读文档或机器可读文档。

    【讨论】:

    • 谢谢你,声音。我一直在等待其他答案,但他们现在似乎没有来。按照同样的例子,像 /cars/types 这样的东西也是我同事最喜欢的选项,但我仍然觉得人们期望在 /cars 下找到的是.. . 一堆汽车(我的意思是它们的代表),而不是其中的值列表...
    【解决方案2】:

    我的情况类似,但我有大量字段,每个字段都有大量可能的值,在某些情况下,这些值来自层次结构,因此我的字段是一个字符串数组。 (借用您的示例:您可能想要记录制造汽车的工厂,而不是一维列表,这些列表按大陆、国家和州组织)。

    我想我将实现一个 /taxonomies 资源来向用户提供所有数据。我看到 WordPress 使用了类似的方案 (http://v2.wp-api.org/reference/taxonomies/),虽然我还没有仔细研究过。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-27
      • 2014-01-24
      • 1970-01-01
      • 2021-05-22
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多