有效的 URIs¶
有效的 URIs(有时也称为更具体的术语 URL [1])是设计可用 HTTP API 的核心。统一资源标识符由 RFC 3986 定义,其在 HTTP 中的使用在 RFC 7230#section-2.7 中进行了阐述。URI 是 API 中资源的标识符,也用于在网络上定位和寻址该资源。
URI 分为几个部分:scheme、authority、path、query 和 fragment(请参阅 RFC 3986 以获取更多详细信息)。作为 API 服务开发人员,path 和 query 最为相关;fragment 通常不会发送到服务,并且对 scheme 和 authority 的控制机会和理由也很少。
以下内容将仅关注 path 和 query。
值得了解的事项¶
path 和 query 的值区分大小写。也就是说,如果您有两个看起来相似的 URI,
http://example.com/foo/BAR?dEtail=1和http://example.com/foo/bar?detail=1,它们并不等效。服务器应用程序可以选择规范化 URI,但这不推荐,因为它不符合常用用法,也不符合 RFC 7230#section-2.7.3。虽然 path 经常看起来像一个层次结构路径(
/collection/item/sub-resource/detail),类似于磁盘上文件的完整文件名,但这只是为了方便起见,并且是使 URI 易于人类消费的副产品。事实是,整个 URI 标识资源,而不仅仅是路径的最后一个片段。URI 设计的全部意义 [2] 是使 URI 易于人类以有意义的方式消费,无论是 API 的用户还是 API 的未来维护者。
URI 设计通用建议¶
注意
这远非详尽的列表。这仅仅是从我们可以积累有关如何构建良好 URI 的合理建议开始的地方。
由于单个 URI 标识单个资源,因此在构建服务时,还需要保持以下两点:
任何资源应该只有一个 URI。在可能的情况下,不要提供多种引用相同事物的方式。使用 HTTP 重定向来解析间接请求到正确的规范 URI,并使用内容协商来请求不同的表示形式。
任何给定的资源,由于应该只有一个 URI,应该响应所有相关的 HTTP 方法,而只在该 URI 处响应,而不要为某些方法提供辅助 URI。例如
使用
GET /resources/1322b203bdc64c13b6e72b04d43e8690 DELETE /resources/1322b203bdc64c13b6e72b04d43e8690
绝不
GET /resources/1322b203bdc64c13b6e72b04d43e8690 DELETE /resources/1322b203bdc64c13b6e72b04d43e8690/delete
通常,API 会有 URI 来 表示资源的集合 和该集合中的单个成员,形成层次结构。例如 [3]
GET /birds {"birds": [ { "name": "alpha", "type": "crow" }, { "name": "beta", "type": "jackdaw" }] } GET /birds/alpha { "name": "alpha", "type": "crow" }
这样做是合理的,因为它有助于使 API 的元素易于理解。
如果使用上述层次结构,重要的是所有采用第二种形式的 URI(
/birds/alpha)都具有相同的语义,并且始终标识是此集合的成员的资源(在本例中“是一只鸟”)。OpenStack 中有多个例子违反了这一概念。例如,在 nova 中的 os-cells API 中,可以
GET /os-cells获取单元列表,GET /os-cells/some-name获取有关名为some-name的单个单元的信息,以及GET /os-cells/details获取与GET /os-cells相同的信息,但具有更多详细信息。对于这个特定的例子,一种方法(有几种选择)是在保持 URI 语义的同时,使用 query 来增强现有的集合 URI,以指示对更多详细信息的渴望 [3]
GET /os-cells?details=true
待办事项
对于布尔查询参数的最佳表示方法,目前尚存在未解决的争论。任何
details=true、details=1或details都有意义。上述内容不应被视为对任何 query 格式的支持。相反,它仅仅是为了演示 URI path 部分中更清晰的语义。
复杂查询¶
在某些情况下,可能需要返回与一组过滤条件匹配的资源集合。对于这些情况,使用 GET 方法,并创建一个将所有要求连接起来的查询字符串。例如,如果您需要返回所有蓝色且具有迁徙性且会游泳的鸟类,则 URI 将如下所示:
GET /birds?color=blue&migratory=true&swimming=true
URI 的长度限制因使用的服务器和客户端而异。最严格的是一些浏览器,它们具有大约 2K 的最大 URI 长度,而 Apache 等 Web 服务器将 URI 限制在约 8K 左右。如果表达请求的复杂要求所需的 URI 长度可能超过这些限制,可以使用 POST 方法,并将过滤条件传递到请求主体中。
脚注