首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >更新/创建分层资源REST

更新/创建分层资源REST
EN

Stack Overflow用户
提问于 2012-11-05 23:28:21
回答 4查看 1.9K关注 0票数 21

我正在开发一个REST API,我正在尝试理解如何处理分层资源。

背景

让我们从一个简单的例子开始。在我的应用程序接口中,我有UsersUser profilesReviews

  • Users必须具有关联的用户配置文件(一个用户配置文件仅对应于一个User)
  • Users可能关联了一个审核(一个审核仅对应于一个用户)

用户的资源表示应该是:

代码语言:javascript
复制
User: {
   "u1": "u1value", // User's attributes
   "u2": "u2value",
   ...
   "links": [{
       "rel": "profile",
       "href": "http://..." // URI of the profile resource
   }, {
       "rel": "review",
       "href": "http://..." // URI of the review resource
   }]
}

用户配置文件资源表示形式应为:

代码语言:javascript
复制
UserProfile: {
   "p1": "p1value", // Profile attributes
   "p2": "p2value",
   ...
   "links": [{
       "rel": "owner",
       "href": "http://..." // URI of the user resource
   }]
}

审阅资源表示形式应为:

代码语言:javascript
复制
Review: {
   "r1": "r1value", // Review attributes
   "r2": "r2value",
   ...
   "links": [{
       "rel": "owner",
       "href": "http://..." // URI of the user resource
   }]
}

资源URI可以是:

对用户的

  • http://api.example.com/users/{userid}:访问权限resource
  • http://api.example.com/users/{userid}/profile:对用户配置文件的访问权限resource
  • http://api.example.com/users/{userid}/review:对用户的审查资源

的访问权限

创建资源:创建用户的正确方式是什么?

现在我想创建一个新用户:

  1. POST http://api.example.com/users {"u1": "bar", "u2": "foo"}和我得到了新的userid = 42
  2. POST http://api.example.com/users/42/profile {"p1": "baz", "p2": "asd"}
  3. PUT http://api.example.com/users {"u1": "bar", "u2": "foo", links: [{"rel": "profile", "href": "http://api.example.com/users/42/profile"]}

我的担忧是:

  • 如果在1和2或2和3之间中断了怎么办?
  • 在3)中,服务器是否应该自动更新http://api.example.com/users/42/profile中的链接,以指向正确的owner?
  • Updating链接字段是创建关系的正确方式?或者我应该跳过步骤3),让系统根据URI约定猜测关系?(我在几本书上读到URI应该被认为是不透明的。)
EN

回答 4

Stack Overflow用户

发布于 2013-04-02 10:02:33

你的担忧是有根据的,你的问题列表是正确的。如果我可以建议的话,您的方法看起来非常像是使用关系数据库方法并执行插入,从用于下一次插入的序列中检索PK,等等。

让服务器维护参照完整性

作为观察,即使遵循您的原始方案,也完全省略了步骤3。检索用户文档时可见的links中的URI应由服务器基于配置文件记录的存在而生成。

例如,如果使用关系后端,则选择from USERS以获取用户记录。接下来,从配置文件中选择。如果存在记录,则修改返回数据结构以包括引用。

POST整个文档

解决您提出的其他问题的一种常见方法是允许将整个文档发布到用户URL (如MongoDB等NoSQL数据库)。这里的文档是用户和配置文件:

代码语言:javascript
复制
{ 
   "u1": "bar",
   "u2": "foo",
   "profile": {  
                 "p1": "baz",
                 "p2": "asd"
              }
}

在此方法中,服务器上的端点接收嵌套结构(文档)并执行INSERT into USERS,检索PK,然后使用此PK执行INSERT into PROFILES。在服务器端执行此操作可以解决以下几个问题:

  1. 事务可以是原子的
  2. 客户端和服务器之间只有一个网络交换
  3. 服务器执行繁重的任务,可以验证整个事务(例如,如果配置文件无效,则不会创建用户)
  4. 不需要执行步骤3。

请注意,这种方法是对上面详细介绍的API的补充-您仍然希望能够直接访问用户的配置文件。

GET - client可以指定字段

与老牌公司的API进行比较是很有趣的。以LinkedIn为例。在他们的developer API中,用户的默认GET只返回用户名、标题和URI。

但是,如果请求指定了其他字段,则可以获取嵌套数据,例如,http://developer.linkedin.com/documents/understanding-field-selectors中的第二个示例返回用户的姓名和他们所担任职位的公司名称列表。您可以为Profiles和Reviews实现类似的方案。

用于更新文档属性的修补程序

有了插入和查询,可能值得考虑如何更新(补丁)数据。覆盖一个字段是很明显的,所以你可以,例如,修补http://api.example.com/users/42如下:

代码语言:javascript
复制
{ 
   "u1": null,
   "u2": "new-foo",
   "profile": {  "p1": "new-baz"}
}

这将取消设置u1,将u2设置为new-foo,并将配置文件的p1更新为new-baz。请注意,如果缺少字段(p2),则不会修改该字段。正如this answer中解释的那样,补丁比旧的PUT更可取。

如果您只需要更新配置文件,请将新的配置文件记录直接修补到http://api.example.com/users/42/profile

删除应级联

最后,删除可以使用DELETE方法来完成,该方法指向您想要删除的资源-可以是User、Profile或Review。实现级联删除,这样删除用户会删除他/她的个人资料和评论。

票数 17
EN

Stack Overflow用户

发布于 2013-04-08 18:49:32

你应该坚持使用HATEOAS,并取消引用你在响应中得到的URL:

为了便于访问,假设User.profile包含带有rel == profilelinkhref

创建用户

有了你描述的帖子。但是它不应该返回一个id,而应该返回一个用户,以及它的链接。

代码语言:javascript
复制
User: {
   "u1": "bar", // User's attributes
   "u2": "foo",
   ...
   "profile": "http://api.example.com/users/42/profile",
   "links": [{
       "rel": "profile",
       "href": "http://api.example.com/users/42/profile"
   },
   ...
   ]
}

在这一点上,User.profile的配置文件资源(可以是http://api.example.com/users/42/profile,或者您将来迁移到的任何位置)是默认配置文件应该是的任何内容,例如空文档或只填充了所有者链接。

更新配置文件

代码语言:javascript
复制
profile = GET User.profile
profile.p1 = "baz"
profile.p2 = "asd"
PUT profile to the same url you just dereferenced

通过取消引用文档上的href,而不是使用从响应中获得的id来构建urls,当API发生变化时,您的客户端将不必进行更改。就像当-profile被移动到http://profiles.cdn.example.com/时--profile获取一个p3值

“旧的”API客户端将继续工作,而无需更改任何代码。

票数 2
EN

Stack Overflow用户

发布于 2013-04-04 14:56:57

实际上,从成功的步骤(1)开始,您应该得到创建的HTTP代码201和新创建的资源的地址(URL),而不仅仅是ID号。如果第(2)步失败,REST API应该指出问题是否出在客户端,比如格式错误的文档(问题代码4xx)或服务器(5xx)。例如,如果在此期间删除了资源42,则应返回未找到代码404。

这就是无状态REST API的问题所在--它们不能支持由多个请求组成的事务。要实现这一点,您必须在服务器上维护一个会话(状态)。

顺便说一句,示例中步骤(3)中的URL建议您替换所有用户,并且可能应该阅读http://api.example.com/users/42

您可以选择一次提交完整的user+profile文档,在一个原子事务中将其拆分为两个数据库记录,或者允许持久化部分用户数据,即没有配置文件的用户。

选择取决于上下文。例如,用户没有配置文件(所以它可以由用户提供)可能是完全没有问题的。相反,拥有不属于任何用户的配置文件记录可能是不可接受的。关于实施此逻辑的讨论超出了您的问题的范围,并将根据您选择的持久存储(数据库)的类型而有所不同。关系数据库使用外键执行此操作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13235201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档