RESTful API 设计:查询参数的列表值选项

RESTful API design: list value options for query param

假设您正在 API return

处构建一个资源列表
[GET] /resources
=> 
[
 {.. id: 1, foo: "A" ..}, {.. id: 2, foo: "B" ..}, {.. id: 3, foo: "A" ..}
]

可以使用 query param 进行过滤:

[GET] /resources&foo=A
=>
[
 {.. id: 1, foo: "A" ..}, {.. id: 3, foo: "A" ..}
]

到目前为止,还不错。

现在要求您创建一个端点,其中 return 是 foo 的可用值;
您希望哪个端点 return 可用于过滤资源的选项?


我的建议是使用HTTP方法OPTIONS:

This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action.

[OPTIONS] /resources
=> 
{
  foo: ["A","B"]
}

但恐怕此 HTTP 方法是为 describing the connection itself, like HTTP verbs or CORS 而设计的,而不是描述您的数据域。

确实如此,正如您正确陈述的那样,OPTIONS 方法是为通信选项保留的,而不是内容,它用于 CORS 验证。

我会使用其中之一:

  • GET /resourceTypes?field=foo
  • GET /resource/types?field=foo

您可以将 "types" 替换为对您的情况更有意义的内容,例如 "allowedValues"、"enum" 等...

通常情况下,根据我的经验,在 REST 中可过滤的值是事先已知的,或者您有一个没有预定值的自由搜索字段。

您的实际问题针对的是如何向客户传授特定资源的可用选项。如果您仔细查看 Web,尤其是 HTML,您可能会看到 HTML 使用表单来教导浏览器(=客户端)服务器期望从客户端输入什么以及它的选择可以在发送请求之前采取。

HTML spec contains the descriptions about the syntax and semantics of the respective elements you can use within a form. This way a server could send an option element to let a client chose between a couple or multiple options. Currently, there are a couple of drafts that attempt to translate this concept to other representation formats than HTML, but to my knowledge none of them is yet major enough or has gained widespread acceptance. Among these are some JSON based ones such as hal-forms, halform, ion and hydra

根据Fielding

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types)

application/json 对于真正的 REST 客户端来说不是一个很好的表示格式,因为它缺乏描述类似表单的表示可能具有的各个元素的语义,也缺乏处理规则该表示的消费者应该如何处理妥善处理信息。在这里,上述媒体类型之一肯定是有益的。问题不应该是选择哪一个,而是你想支持多少。您支持的格式越多,任意客户端就越有可能与您的系统交互。

客户端和服务器应始终使用内容类型协商来就双方都能理解的表示格式达成一致,以交换数据。这减少了互操作性问题,因为两个客户端都知道如何处理和解释约定的媒体类型。如果没有可用的通用表示格式或客户端向服务器发送了不熟悉的表示,服务器将通知客户端其无法为客户端提供内容。

围绕 REST 的全部目的是允许服务器在未来自由发展,而不必担心破坏客户端。这在具有许多不受您控制的不同客户端和 API 的区域中尤其有益。 EDI 将是这样一个领域,可以为您提供更好的可视化内容。在这里,许多 ERP 系统和应用程序必须交换业务文档,例如订单和发票。有一些标准化的表示格式,如 EDIFACT,尽管有大量自定义格式在使用,这使得整个领域非常有趣。您基本上不想为与之交互的每个 ERP 系统创建自定义客户端(或服务器),而是平等地处理每条消息交换。

对于前端到后端的通信,尽管您实际上并不需要完全成熟的 REST 架构,因为这可能会给您带来更多的负担,而不是它提供的任何好处。 REST 中的事实是,客户端和服务器都必须小心设计以避免耦合。如果只有一个参与者试图忽略 Fielding 设置的约束之一,则可能存在耦合,这会阻止服务器将来添加新功能而不影响客户端或客户端保持与服务交互的能力。

因此,如果您想告诉客户他们对某些资源有哪些选择,请在 Web 上进行定位并使用能够表达该功能的媒体类型,以便客户可以使用它。