【问题标题】:Is this a valid mapping for a REST API?这是 REST API 的有效映射吗?
【发布时间】:2014-01-23 10:15:33
【问题描述】:

我在处理系统的 REST API 时提出了以下映射,用户可以在该系统中创建和管理不同类型的资源。

// READ OPERATIONS
GET /objects               => read collection meta
GET /objects/[id]          => read single element
GET /objects/?[query]      => read a number of elements
GET /objects/?all          => read all elements

// CREATE / UPDATE OPERATIONS
PUT /objects               => possibly create the collection and update its meta
PUT /objects/[id]          => possibly create and update a single element
PUT /objects/?all          => update the entire content of the collection
POST /objects              => create new objects or update existing objects
PATCH /objects             => partially update the collection meta
PATCH /objects/[id]        => partially update a single element
PATCH /objects/?all        => partially update all the elements
PATCH /objects/?[query]    => partially update a number of elements

// DELETE OPERATIONS
DELETE /objects            => delete the collection
DELETE /objects/[id]       => delete a single element
DELETE /objects/?all       => empty the collection
DELETE /objects/?[query]   => delete a number of elements

这里有一些关于系统的更多信息:

  • 每个资源既可以是简单资源,也可以是类似集合的资源;
  • 每个资源,不管是否是集合,都有自己的属性需要访问和操作;
  • API 必须支持批量(而非批量)操作。

我还研究了以下替代方案:

  1. 使用/collection 访问集合的元素集,使用/collection?meta 访问集合自身的数据;
  2. 使用全新资源访问集合自己的数据,例如/collections/path/to/collection

我不喜欢替代 n。 1)因为在我看来,它在语义上很差。相比之下,当我提到一个盒子时,我实际上指的是盒子本身,而不是它的内容。

我不喜欢替代 n。 2) 因为一个资源最终将自己的数据暴露给另一个资源,复制 url 并使“我应该使用哪个 url”的问题不像我希望的那样微不足道。

因此,我的问题:

  1. 我为 REST API 提出的映射是否有效、正确?是否尊重 REST 原则?我不是在问它是否是最好的映射。我在问它的​​有效性。
  2. 如果不是,哪一种方案更好,为什么?

请原谅我的英语,我不是该语言的母语人士。

【问题讨论】:

  • 你的英语很棒。你的 API 设计也不错:)
  • 也许我应该为我的评论提出一个问题,但我想知道“PUT”和“PATCH”之间的区别。在服务器中,您将在每个操作中执行哪些操作?我问是因为它们看起来非常接近。以编程方式它们有什么不同?
  • @BrianKelly:谢谢伙计!
  • @edubriguenti:PATCH 允许部分更新(PUT 始终需要整个资源主体)。而且,它既不是幂等的,也不是安全的(PUT 是幂等的)。恕我直言,PATCH 更适合批量更新,您只想更新特定资源集中的给定属性子集。这同样适用于 POST 与 PUT。我认为不应该使用幂等方法进行批量更新。
  • @BrianKelly:将您的评论转化为答案,以便我将其标记为已接受。

标签: http rest url mapping bulk-operations


【解决方案1】:

我认为 API 设计看起来不错,但后来我在开始时重新阅读了您的这条评论:

用户可以在其中创建和管理不同的资源 类型。

如果您系统的资源属于不同类型,为什么要使用仅适用于通用 objects 的中立、无类型 API 来公开它们?

RESTful API 设计的第一部分是识别系统中的名词,这些名词应被强烈考虑作为 URI 公开的候选对象。我强烈建议您尝试比object 更具体,并使用更清晰的 URI 对系统的业务功能进行建模。

而且你的英语很好!

【讨论】:

  • 尽管我提出的映射是一个通用示例,说明如何处理集合的元和元素,但您的观察是准确的,一定要牢记在心。谢谢!
【解决方案2】:

首先,URI 的语义与 REST 无关。 “RESTful URI”几乎是一个矛盾的说法。 URI 必须遵循的唯一约束是 RESTful 是它引用一个且只有一个资源。

显然,这并不意味着 REST URI 可以是晦涩难懂的。它们应该尽可能清晰、直观和具有描述性,但是您决定使用的任何方案都可以,只要其一致即可。如果您对此如此担心,则意味着您可能没有使用 HATEOAS,应该看看它。

其次,您没有考虑媒体类型,这就是为什么您最终会遇到使用 URI 来指定不同媒体类型的问题。假设检索集合的所有元素应该很简单:

GET /objects

检索集合的单个元素应该是:

GET /objects/[id]

现在,如果客户端只需要资源的元数据,无论是集合还是单个元素,它应该通过 Accept 标头指定,而不是通过转到您在文档中指向的单独 URI,或者更糟糕的是,通过添加查询字符串参数。

因此,例如,如果您的对象的媒体类型是 application/vnd.mycompany.myobject+json,则您的客户端在 Accept 标头中使用该媒体类型时会获得完整的对象表示,并使用类似 application/vnd.mycompany.myobjectmetadata+json 的内容获取元数据.

我想这可能不是您所期望的,但这就是 REST。您的文档和设计工作应该专注于您的媒体类型,而不是您的 URI。当你使用 HATEOAS 时,URI 设计是无关紧要的,如果你不使用 HATEOAS,你就没有使用 REST。

【讨论】:

  • 我明白你对 HATEOAS 的看法,这正是我研究 JSON-HAL 和 JSON-LD 的原因。我真的很喜欢 JSON-HAL 信息模型处理子资源的方式。也就是说,无论“Accept”标头的值是什么,适当的 REST API (AFAIK) 应该始终为每个给定的 URI 输出相同资源的表示,无论该表示的超媒体类型最终可能是什么。
  • 也许我一直不清楚我所说的“元”是什么意思,并且可能使用了错误的词。考虑一个资源,特别是资源集合,它具有自己的用户可编辑配置。这就是我想要的“元”。
  • 经过更多阅读和研究与 REST 相关的文档和文档后,我现在理解了我的 URI-first 方法中的错误。佩德罗,谢谢你为我指明了正确的方向。虽然我仍然无法理解“接受”标题的事情,但我意识到我从错误的角度处理了整个元/元素问题。
  • 一个“合适的”REST API 应该简单地遵循底层协议的标准。使用 HTTP,如果客户端想要给定资源的不同表示,他会更改媒体类型,而不是 URI。例如,当客户端请求 JSON 时,您可以返回一个机器友好的表示,而当他请求 text/html 时,您可以返回一个人类友好的表示。
  • 是的,我理解并完全同意。我不明白的是为什么您建议使用“接受”标头来选择要包含在表示中的资源的哪一部分(元与元素)。至少据我所知,这与简单地要求资源的某种表示形式不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-07
  • 2011-04-15
相关资源
最近更新 更多