使用RESTful URL标识集合子集



假设我想获得我的公司在缅因州拥有的所有商店的列表。从概念上讲,此请求可以被视为

/stores?state=Maine (All stores such that the state of the store is Maine)

/states/Maine/stores (All of Maine's stores)

哪个更RESTful,为什么?从我的理解来看,两者似乎各有利弊。

编辑:

我最初的例子有一个问题,将存储作为状态的子源可能没有直观的意义,所以这里有另一个更详细的例子:假设我可以按ISBN或按标题在全球范围内识别书籍(假设没有作者对自己的两本书命名相同)。因此,在该方案下,/books/0-525-94892-9/authors/Ayn_Rand/books/Atlas Shrugged将参考同一本书。所以,如果我想要所有的书,我是GET /books?author=Ayn_Rand还是GET /authors/Ayn_Rand/books

哪个更RESTful,为什么

两者都是相同的RESTful(尽管从技术上讲,RESTURI是不透明的,所以这无关紧要)。哪个最适合您的用例取决于您的资源继承权。

从你的书的例子来看,我会使用ISBN,因为它是其他地方使用的那本书的罐头标识符。可能还有其他名为《阿特拉斯耸耸肩》的书,也可能有其他名为"艾恩·兰德"的作者,或者同一作品的衍生版可能会更改名称,或者在经过充分编辑的情况下列出第二位作者。您需要提供至少两个数据,{author-name, book-name},甚至可能是{publication-year},以唯一地标识该书。对于ISBN编号,您只能使用一个基准来识别图书。

/authors/{author-name}/books/{book-name}的请求可能会返回302 Found响应或更好的响应,返回具有/books/{isbn}Content-Location标头的书籍,并在响应中使用rel="canonnical self"链接指向资源的ISBN URI。

编辑
我将从我自己的API中提供一个示例:
我们有jobscontactssites。所有这些都是顶级资源。站点表示具有地址的物理位置。联系人通常代表一家公司,但有时是个人或学校等组织。站点有一个owner,它是一个联系人。当你去那个地址时,业主就是标牌上的名字。工作是顶级资源。作业具有clientsitesite_owner。作业的客户是联系人(并非所有联系人都是客户),作业的站点所有者是作业时站点的所有者,因为站点的所有者可能会随着时间的推移而改变,因为用户易手等等。我们有时也会为非站点所有者的客户做作业(即分包商工作)。我们需要保留在一个站点上完成的所有工作的历史记录,无论客户是谁,当时谁拥有这座建筑等。
因此,在特定客户的站点上完成工作的作业列表可以在几个URI下访问,/contacts/{id}/sites/{id}/jobs/sites/{id}/jobs?client={id}/contacts/{id}/jobs?site={id},但实际上它们只是作业列表上的过滤器,完全等同于/jobs?client={id}&site={id},事实上,所有URI都是有效的,最终到达同一个PHP文件,将相同的变量设置为相同的值,并运行相同的查询,有些只是采取更迂回的路线,再调用几个include
我允许所有这些不同URI的原因只是因为它允许我的用户在他们的导航层次结构中"上升"一两级(变量"面包屑"取决于到达列表的路径;这会稍微改变返回的表示形式),而且因为数据集是实时的,对于你可能正在查看的东西来说是高度动态的,因此HTML结果是不可访问的,因此不重新使用cannonical URI的折衷方案提供了比缺点更多的好处。

这一切的收获是:

  • 为您的资源使用一个唯一的标识符,或者如果您的资源本身没有一个(例如ISBN),则创建一个(id)

  • 您选择的URI与您的API是的RESTful无关

除非/states/states/Maine也是系统中的资源,否则我将使用第一个示例。

在您给出的两个示例(states/stores和authors/books)中,我将使用后一种方案。

它允许您以直观的方式公开各种不同的资源。URI清楚地表明了您期望的资源,并且它将使用中的约束表示为"路径",而不是?key=value&foo=bar&so=on...的混乱

请允许我解释一下。。。

/authors/

将返回所有作者资源的列表。

/authors/Ayn_Rand/

将归还Ayn Rand资源,其中可能包含与Rand女士本人有关的信息。

/authors/Ayn_Rand/books

会寄回一份艾恩·兰德的书单。这可能看起来像是一个"简单"的图书列表:

[
{
title: 'Atlas Shrugged',
genre: 'Fiction'
slug: 'atlas_shrugged'
},
{
title: 'The Fountainhead',
genre: 'Fiction',
slug: 'the_fountainhead'
},
{
title: 'Capitalism: The Unknown Ideal',
genre: 'Non-fiction',
slug: 'capitalism_the_unknown_ideal'
}
]

你可能希望使用也使用超媒体严格参考书籍的ISBN:

...
{
title: 'Atlas Shrugged',
genre: 'Fiction',
location: '/books/0-525-94892-9'
},
...

最新更新