何时在RESTful API中使用嵌套资源


16

我有两个资源:用户和链接。

用户可以具有几个与之关联的链接。我已经设计了RESTful API,以便您可以通过以下URI访问与用户关联的链接:

/users/:id/links

但是,我总是需要一个仅用于链接的URI –有时我可能想要所有链接,无论用户是谁。

为此,我有:

/links

听起来还好吗?有两个链接的URI吗?

我想知道是否应该使用URI来访问用户的链接,例如:

/links/user/:id 要么 /links/?user=:id

这样,我只有一个链接资源。


3
嗯..这似乎更优雅:/links/user/:id
theMarceloR

7
@theMarceloR:这是我十分清楚的三个例子中的唯一例子。是链接资源还是用户资源?URI使用嵌套资源方法(/users/:id/links)或查询字符串方法(/links/?user=:id)的模棱两可,因为它实际上是一个查询。/links/user/:id在某些框架中可能看起来不错和/或更容易路由,但实际上却很混乱。
Aaronaught

Answers:


16

不,对于同一个“事物”拥有多个资源没有什么错,在这种情况下为链接列表。

我们最近正面临着同样的问题。我们的决定是将所有没有严格所有权的资源都嵌套。换句话说,链接将在以下条件下建模

/links -- all links
/links/:linkid -- a particular link

然后,链接集合上的过滤器表示为查询参数。因此,要获取某个用户的链接,可以使用:

/links?user=/users/:userid

这也使过滤器的组成更加容易:

/links?user=/users/10&since=2013-01-01

从概念上很容易理解-您有一组项目,并向其中添加了过滤器。

话虽这么说,没有比其他任何URI命名方案更“ RESTful”的了。这只是我们发现的一种惯例,使我们的开发人员易于理解和接受。REST不在乎您在资源标识符中放入什么。


1
“没有严格所有权的所有资源都不能嵌套”,这听起来像是一条好规则。谢谢你
奥利弗·约瑟夫·阿什

5
我要说的,对于一个物理实体拥有多个资源是有问题的,但这实际上不是问题。每个单独的链接都有一个规范的URL(links /:id),而上面的每个资源实际上都是一个应用了过滤器的单个资源(/ links)。另外,我?user=users/:userid对查询字符串中的感到很奇怪;正义有什么问题?userid=:userid
Aaronaught

2
@Aaronaught:坚持使用uri而不是裸ID的原因是,客户端可以平等地对待所有资源标识符,也就是说,客户端只需要知道“此用户由"/*******";其中*的是不透明的。但是该标识符始终可以用来引用该资源(如带有链接的内容),获取该资源的最新版本,依此类推。uri的内容仅由原始服务器理解。这也意味着,如果标识符需要更改,例如/realm/:businessid/users/:id,客户端根本不需要更改。
SingleNegationElimination

@TokenMacGuy:对不起,我不理解您的评论的任何部分。/users/:userid/links和之间的实际区别是/links?userid=:userid什么?在这两种情况下,标识符都不会更改,它们会获取该资源的当前版本,客户端将以相同的方式对待它们。对此没有规范的URL,因为它不是资源,而是查询,因此它们只是两种不同类型的查询语法。如果URL结构发生变化,我也不清楚客户端如何不需要更改。除非安装了301,否则这被认为是REST的重大更改。
亚罗诺(Aaronaught)2013年

1
@Aaronaught:我可能误会了您的担心。假设/links支持查询接口,/links?user=/users/123允许使用黑盒方法来访问客户端中/links?userid=123不支持的资源标识符。后者要求客户了解用户ID是什么以及如何获取它,大概是从它从/users/123或获得的资源中/links/456/user。前者意味着客户可以使用未修改的uri;假设/links/.../user给出了超媒体响应(例如带有Location:标题)。
SingleNegationElimination

1

因此,我担心的是:/ users /:userid / links返回“链接”,但如果未标识user_id,则应返回404。

然而

/ links?userid =:userid可能会返回一个空列表(实际上是200),这实际上可能是一个错误。而且很有可能。

尽管两者都起作用,但嵌套为您提供了其他功能,您可以在以后使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.