使用RESTful URL标识集合子集

时间:2012-11-28 18:55:41

标签: rest

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

/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会引用同一本书。所以如果我想要Ayn Rand的所有书籍,我会GET /books?author=Ayn_Rand还是GET /authors/Ayn_Rand/books

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

在你给出的两个例子中(州/商店和作者/书籍),我会使用后一种方案。

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

的混乱

请允许我解释......

/authors/

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

/authors/Ayn_Rand/

将返回Ayn Rand资源,其中可能包含有关Rand女士的信息。

/authors/Ayn_Rand/books

将返回Ayn Rand的书籍清单。这可能看起来像一个“简单”的书籍清单:

[
{
    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'
},
...

答案 2 :(得分:1)

哪个更RESTful,为什么?

两者都是RESTful(尽管从技术上讲,REST URI是不透明的,因此无关紧要)。哪个最适合您的用例取决于您的资源层次。

从您的图书示例中,我会使用ISBN,因为它是其他地方使用的该书的标准标识符。可能还有其他一些名为“Atlas Shrugged”的书籍,可能还有其他作者称为“Ayn Rand”,或者相同作品的衍生版本可能会更改名称,或者如果编辑得当,则列出第二个作者。您需要提供至少两个数据{author-name, book-name},甚至可能{publication-year}来唯一标识该图书。使用ISBN号,您只需使用一个数据来识别该书。

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

修改
我将从我自己的API中提供一个示例:
我们有jobscontactssites。所有这些都是顶级资源。站点代表带有地址的物理位置。联系人通常代表公司,但有时候是个人或像学校这样的组织。网站有一个owner是一个联系人。当您前往该地址时,所有者是标志上的名称。工作是顶级资源。工作有clientsitesite_owner。作业的客户端是联系人(并非所有联系人都是客户端),作业的site_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只是因为它允许我的用户在其导航层次结构中“升级”一级或两级(变量“breadcrumbs”取决于到达列表所采用的路径;它稍微改变了返回的表示),并且因为数据集是实时的,对于您可能正在查看的事物是高度动态的,因此HTML结果是无法访问的,因此不重复使用规范URI的权衡提供了更多的好处而不是低谷。

所有这一切的收获:

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

  • 您选择的URI与您的API的RESTful

  • 无关