2013-01-22 26 views
5

我被要求设计和实现一个RESTful API,并一直在研究最佳实践,但到目前为止只有关于资源表示的概念。我发现的大多数可用示例似乎都将重点放在使用一系列GET获取连接结构的API客户端上。带有链接的REST资源表示,与PUT和GET兼容

我已经看过:

http://www.restapitutorial.com/media/RESTful_Best_Practices-v1_1.pdf

http://www.youtube.com/watch?v=HW9wWZHWhnI

除其他在线资源(我限制在2个链接恕无法一一列举)。它们都很棒,但并没有真正解决我的设计问题。

大多数最佳实践文档建议两件事情对我来说在冲突看咯:

1)REST服务应该代表的资源之间的链接数据关系

2)从“PUT”请求客户端应该是完整的表示形式,与服务器上的表示形式相同。

从我的观点来看,麻烦在于,典型资源中的链接以及其他一些属性是只读的,因此无法更新。服务器在装置上期望它们是原样的,并且如果它认为客户端正在尝试更新它们,则返回一个错误。实际上,当我查看以JSON表示的典型资源时,其中大部分是逻辑上不能/不应该被替换的数据。例如。

{ 
"link": { "rel":"self", "href":"http://example/project/12345" }, 
"team": { 
    "link": { "rel":"self", "href":"http://example/project/12345/team" }, 
    "title": "The project team" 
    }, 
    "title": "The Big Project" 
} 

这里充其量只有两个标题文本将写入到这个资源的客户机(团队成员可能是通过团队链接可变)。

所以我应该要求PUT完全按原样包含所有“链接”元素,它们纯粹是逻辑的和只读的(请注意,在示例中,团队无法重新链接,因为资源定义它作为项目团队 - 在这种情况下可以改变,但对于许多具有更严格集装箱的资源类型,这不适用)?

是否存在标准模式或反模式来表示REST中具有多个链接的资源?我没有被要求提供特定的REST变体,比如HATEOAS,尽管我倾向于在可能的情况下以理论上的“正确性”为目标。换句话说,如果“官方”REST会希望客户把整个资源,链接和所有内容放在一起,那么这可能是我会做的。

真的很感激一些支持GET和PUT并因此必须处理这个问题的现实世界复杂的非叶REST资源的例子。当我搜索时,我得到很多意见,并且很多例子显示了GET如何很好地工作。 。 。但到目前为止,我还没有看到一个记录良好的例子,显示PUT除了一个简单的叶资源(即不包含任何链接,除了可能是自引用外)。

回答

1

您应该在您的媒体类型定义它时放置一个“完整”表示。如果你正在设计你自己的媒体类型,你的规范应该定义哪些部分是可变的,哪些是不可变的。的商事目录协议,例如,定义a "body" member其旨在包含可变数据:

通常,当主体构件存在,处理器应该期望 身体中存在的值是潜在可变的(通过一个 例如HTTP PUT或POST),并且应该期望身体成员 以外的任何值是不可变的;即(可能)在 插入但不在更新时写入。服务器是免费的,当然允许或拒绝资源的任何部分的可变性。但是,“身体”成员的存在带来了关于 数据在该成员之内和之外的可变性的强烈暗示。

这不是一个标准(虽然它对我来说非常有用,我希望它变成一个(眨眼))。请注意,服务器可以随意使用客户端发送的表示做任何事情;任何HTTP服务器最强烈的要求是它试图执行客户端的意图(如果能够和允许的话)。如何以及它在多大程度上确实是您的特定应用程序的关注点,这就是为什么您没有在任何关于它的规格中找到太多东西的原因。

实际上,我没有发现它对服务器验证表示的链接或其他不可变部分有用;他们完全被忽略。这可能导致客户决定他们可以省略这些。再次,在实践中,我没有发现这是一个问题。

+0

谢谢。我的铅笔设计包含一个“属性”部分,它与“身体”成员的想法非常相似。我也在考虑将这些事情分解到他们自己的叶子资源中,这会为我的设计增加5或6种资源类型(不好),但是相当简化PUT方法(好) –

3

基本上,GET请求将返回一个序列化为定义格式的资源,以及关于该资源的元数据(它们一起构成资源的表示形式)。当你放弃一个表示时,它不需要包含元数据,也不需要与原始(或任何后续)GET请求的格式相同。服务器将根据您提供的表示更新资源。

来自HTML的示例是<head><body>元素,它们提供有关资源的元数据和资源表示;和text/htmlapplication/x-www-form-urlencoded内容类型,它们以两种不同的格式传输资源表示,前者与元数据,后者没有。在发布后获取资源时,您不希望收到application/x-www-form-urlencoded格式的数据!

我不确定你的意思是“REST变种”。只有一个REST。如果您指的是其他基于HTTP的API,请不要将它们称为REST。有关API样式的更多详细信息,请参见Classification of HTTP-based APIs

最后,您要求提供非叶PUT请求的示例。我不知道你所说的无叶的意思是什么,我能想到的两种类型:

  1. 集合
  2. 子资源

集合 比方说,你有车目录,可在/cars。如果您决定要清除所有车辆,则可以执行DELETE /cars/1,DELETE /cars/2等等,或者您可以选择PUT /cars,其中包含空的车身或没有内容的阵列。后者显然会更有效率。

子资源 继续这个主题,让我们说,有一辆车,/cars/1这是这样表示:

{ 
    "model":"Model-T", 
    "mfgr":"Ford", 
    "colour":"black" 
} 

现在,你可能希望允许通过网址,这样可以访问这些字段作为/cars/1/mfgr,其将返回Ford或者可能{"mfgr":"Ford"}。现在URL /cars/1代表一个非叶资源。但是,在URL中添加新的表示形式仍然没有问题。因此,这也会更新子资源URL的值。

最后,您可能需要查看HAL格式以通过JSON传输超文本。

+0

谢谢。对于我来说,HAL看起来像一个可行的选项(通过ROAR gem),因为我很可能会选择Ruby的葡萄珠宝来实现API。 –

+0

很好的答案。我喜欢链接中的API分类的初始成本,维护成本,演进成本。 – codeasone